about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-02 05:15:39 -0800
committerbors <bors@rust-lang.org>2013-03-02 05:15:39 -0800
commit2304fe6208404ce952aaa37e7634db570ff71f6c (patch)
treeff90158dc320e3c59e5572a41adbbd148bf82cf7
parent5aca7d6aef2f5e18b640d918b243a71fc893a65b (diff)
parent035233a25907af8206d254878e7e04048fcac95e (diff)
downloadrust-2304fe6208404ce952aaa37e7634db570ff71f6c.tar.gz
rust-2304fe6208404ce952aaa37e7634db570ff71f6c.zip
auto merge of #5196 : thestinger/rust/ord, r=catamorphism
This allows `TreeMap`/`TreeSet` to fully express their requirements and reduces the comparisons from ~1.5 per level to 1 which really helps for string keys.

I also added `ReverseIter` to the prelude exports because I forgot when I originally added it.
-rw-r--r--src/libcore/cmp.rs76
-rw-r--r--src/libcore/prelude.rs4
-rw-r--r--src/libcore/str.rs40
-rw-r--r--src/libcore/vec.rs59
-rw-r--r--src/libstd/treemap.rs167
5 files changed, 253 insertions, 93 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index fd99235bd27..d588f0c53b1 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -37,6 +37,70 @@ pub trait Eq {
     pure fn ne(&self, other: &Self) -> bool;
 }
 
+#[deriving_eq]
+pub enum Ordering { Less, Equal, Greater }
+
+/// Trait for types that form a total order
+pub trait TotalOrd {
+    pure fn cmp(&self, other: &Self) -> Ordering;
+}
+
+pure fn icmp<T: Ord>(a: &T, b: &T) -> Ordering {
+    if *a < *b { Less }
+    else if *a > *b { Greater }
+    else { Equal }
+}
+
+impl TotalOrd for u8 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for u16 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for u32 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &u32) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for u64 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &u64) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for i8 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &i8) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for i16 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &i16) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for i32 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &i32) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for i64 {
+    #[inline(always)]
+    pure fn cmp(&self, other: &i64) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for int {
+    #[inline(always)]
+    pure fn cmp(&self, other: &int) -> Ordering { icmp(self, other) }
+}
+
+impl TotalOrd for uint {
+    #[inline(always)]
+    pure fn cmp(&self, other: &uint) -> Ordering { icmp(self, other) }
+}
+
 /**
 * Trait for values that can be compared for a sort-order.
 *
@@ -94,3 +158,15 @@ pub pure fn min<T:Ord>(v1: T, v2: T) -> T {
 pub pure fn max<T:Ord>(v1: T, v2: T) -> T {
     if v1 > v2 { v1 } else { v2 }
 }
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn test_int() {
+        assert 5.cmp(&10) == Less;
+        assert 10.cmp(&5) == Greater;
+        assert 5.cmp(&5) == Equal;
+        assert (-5).cmp(&12) == Less;
+        assert 12.cmp(-5) == Greater;
+    }
+}
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 422d9a6eea0..e4be0cf98dd 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -24,10 +24,10 @@ pub use result::{Result, Ok, Err};
 /* Reexported types and traits */
 
 pub use clone::Clone;
-pub use cmp::{Eq, Ord};
+pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
 pub use container::{Container, Mutable, Map, Set};
 pub use hash::Hash;
-pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
+pub use iter::{BaseIter, ReverseIter, ExtendedIter, EqIter, CopyableIter};
 pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
 pub use num::NumCast;
 pub use path::GenericPath;
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 7dfc52c458a..f1e23f01e7b 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -20,7 +20,7 @@
 use at_vec;
 use cast;
 use char;
-use cmp::{Eq, Ord};
+use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
 use libc;
 use libc::size_t;
 use io::WriterUtil;
@@ -773,6 +773,35 @@ pub pure fn eq(a: &~str, b: &~str) -> bool {
     eq_slice(*a, *b)
 }
 
+pure fn cmp(a: &str, b: &str) -> Ordering {
+    let low = uint::min(a.len(), b.len());
+
+    for uint::range(0, low) |idx| {
+        match a[idx].cmp(&b[idx]) {
+          Greater => return Greater,
+          Less => return Less,
+          Equal => ()
+        }
+    }
+
+    a.len().cmp(&b.len())
+}
+
+#[cfg(notest)]
+impl TotalOrd for &str {
+    pure fn cmp(&self, other: & &self/str) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(notest)]
+impl TotalOrd for ~str {
+    pure fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(notest)]
+impl TotalOrd for @str {
+    pure fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) }
+}
+
 /// Bytewise slice less than
 pure fn lt(a: &str, b: &str) -> bool {
     let (a_len, b_len) = (a.len(), b.len());
@@ -2389,6 +2418,7 @@ mod tests {
     use ptr;
     use str::*;
     use vec;
+    use cmp::{TotalOrd, Less, Equal, Greater};
 
     #[test]
     fn test_eq() {
@@ -3395,4 +3425,12 @@ mod tests {
         assert view("abcdef", 1, 5).to_managed() == @"bcde";
     }
 
+    #[test]
+    fn test_total_ord() {
+        "1234".cmp(& &"123") == Greater;
+        "123".cmp(& &"1234") == Less;
+        "1234".cmp(& &"1234") == Equal;
+        "12345555".cmp(& &"123456") == Less;
+        "22".cmp(& &"1234") == Greater;
+    }
 }
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 0d1be03638a..925d78a3b81 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -15,7 +15,7 @@
 use container::{Container, Mutable};
 use cast::transmute;
 use cast;
-use cmp::{Eq, Ord};
+use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
 use iter::BaseIter;
 use iter;
 use kinds::Copy;
@@ -1425,7 +1425,7 @@ pub pure fn rev_eachi<T>(v: &r/[T], blk: fn(i: uint, v: &r/T) -> bool) {
  * Both vectors must have the same length
  */
 #[inline]
-pub fn each2<U, T>(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) {
+pub pure fn each2<U, T>(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) {
     assert len(v1) == len(v2);
     for uint::range(0u, len(v1)) |i| {
         if !f(&v1[i], &v2[i]) {
@@ -1575,6 +1575,38 @@ impl<T:Eq> Eq for @[T] {
 
 // Lexicographical comparison
 
+pure fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering {
+    let low = uint::min(a.len(), b.len());
+
+    for uint::range(0, low) |idx| {
+        match a[idx].cmp(&b[idx]) {
+          Greater => return Greater,
+          Less => return Less,
+          Equal => ()
+        }
+    }
+
+    a.len().cmp(&b.len())
+}
+
+#[cfg(notest)]
+impl<T: TotalOrd> TotalOrd for &[T] {
+    #[inline(always)]
+    pure fn cmp(&self, other: & &self/[T]) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(notest)]
+impl<T: TotalOrd> TotalOrd for ~[T] {
+    #[inline(always)]
+    pure fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(notest)]
+impl<T: TotalOrd> TotalOrd for @[T] {
+    #[inline(always)]
+    pure fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) }
+}
+
 pure fn lt<T:Ord>(a: &[T], b: &[T]) -> bool {
     let (a_len, b_len) = (a.len(), b.len());
     let mut end = uint::min(a_len, b_len);
@@ -2151,7 +2183,7 @@ pub mod bytes {
     use vec;
 
     /// Bytewise string comparison
-    pub pure fn cmp(a: &~[u8], b: &~[u8]) -> int {
+    pub pure fn memcmp(a: &~[u8], b: &~[u8]) -> int {
         let a_len = len(*a);
         let b_len = len(*b);
         let n = uint::min(a_len, b_len) as libc::size_t;
@@ -2172,22 +2204,22 @@ pub mod bytes {
     }
 
     /// Bytewise less than or equal
-    pub pure fn lt(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) < 0 }
+    pub pure fn lt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) < 0 }
 
     /// Bytewise less than or equal
-    pub pure fn le(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) <= 0 }
+    pub pure fn le(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) <= 0 }
 
     /// Bytewise equality
-    pub pure fn eq(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) == 0 }
+    pub pure fn eq(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) == 0 }
 
     /// Bytewise inequality
-    pub pure fn ne(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) != 0 }
+    pub pure fn ne(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) != 0 }
 
     /// Bytewise greater than or equal
-    pub pure fn ge(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) >= 0 }
+    pub pure fn ge(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) >= 0 }
 
     /// Bytewise greater than
-    pub pure fn gt(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) > 0 }
+    pub pure fn gt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) > 0 }
 
     /**
       * Copies data from one vector to another.
@@ -2429,6 +2461,7 @@ mod tests {
     use option;
     use sys;
     use vec::*;
+    use cmp::*;
 
     fn square(n: uint) -> uint { return n * n; }
 
@@ -3942,6 +3975,14 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_total_ord() {
+        [1, 2, 3, 4].cmp(& &[1, 2, 3]) == Greater;
+        [1, 2, 3].cmp(& &[1, 2, 3, 4]) == Less;
+        [1, 2, 3, 4].cmp(& &[1, 2, 3, 4]) == Equal;
+        [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less;
+        [2, 2].cmp(& &[1, 2, 3, 4]) == Greater;
+    }
 }
 
 // Local Variables:
diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs
index 88e4ade4b82..a093351c4a7 100644
--- a/src/libstd/treemap.rs
+++ b/src/libstd/treemap.rs
@@ -10,12 +10,8 @@
 
 //! An ordered map and set implemented as self-balancing binary search
 //! trees. The only requirement for the types is that the key implements
-//! `Ord`, and that the `lt` method provides a total ordering.
+//! `TotalOrd`.
 
-use core::container::{Container, Mutable, Map, Set};
-use core::cmp::{Eq, Ord};
-use core::iter::{BaseIter, ReverseIter};
-use core::option::{Option, Some, None};
 use core::prelude::*;
 
 // This is implemented as an AA tree, which is a simplified variation of
@@ -39,7 +35,7 @@ pub struct TreeMap<K, V> {
     priv length: uint
 }
 
-impl<K:Eq + Ord,V:Eq> Eq for TreeMap<K, V> {
+impl<K: Eq + TotalOrd, V: Eq> Eq for TreeMap<K, V> {
     pure fn eq(&self, other: &TreeMap<K, V>) -> bool {
         if self.len() != other.len() {
             false
@@ -61,7 +57,8 @@ impl<K:Eq + Ord,V:Eq> Eq for TreeMap<K, V> {
 }
 
 // Lexicographical comparison
-pure fn lt<K:Ord,V>(a: &TreeMap<K, V>, b: &TreeMap<K, V>) -> bool {
+pure fn lt<K: Ord + TotalOrd, V>(a: &TreeMap<K, V>,
+                                 b: &TreeMap<K, V>) -> bool {
     let mut x = a.iter();
     let mut y = b.iter();
 
@@ -78,7 +75,7 @@ pure fn lt<K:Ord,V>(a: &TreeMap<K, V>, b: &TreeMap<K, V>) -> bool {
     return a_len < b_len;
 }
 
-impl<K:Ord,V> Ord for TreeMap<K, V> {
+impl<K: Ord + TotalOrd, V> Ord for TreeMap<K, V> {
     #[inline(always)]
     pure fn lt(&self, other: &TreeMap<K, V>) -> bool {
         lt(self, other)
@@ -97,7 +94,7 @@ impl<K:Ord,V> Ord for TreeMap<K, V> {
     }
 }
 
-impl<K:Ord,V> BaseIter<(&K, &V)> for TreeMap<K, V> {
+impl<K: TotalOrd, V> BaseIter<(&K, &V)> for TreeMap<K, V> {
     /// Visit all key-value pairs in order
     pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) {
         each(&self.root, f)
@@ -105,14 +102,14 @@ impl<K:Ord,V> BaseIter<(&K, &V)> for TreeMap<K, V> {
     pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
 }
 
-impl<K:Ord,V> ReverseIter<(&K, &V)> for TreeMap<K, V> {
+impl<K: TotalOrd, V> ReverseIter<(&K, &V)> for TreeMap<K, V> {
     /// Visit all key-value pairs in reverse order
     pure fn each_reverse(&self, f: fn(&(&self/K, &self/V)) -> bool) {
         each_reverse(&self.root, f);
     }
 }
 
-impl<K:Ord,V> Container for TreeMap<K, V> {
+impl<K: TotalOrd, V> Container for TreeMap<K, V> {
     /// Return the number of elements in the map
     pure fn len(&self) -> uint { self.length }
 
@@ -120,7 +117,7 @@ impl<K:Ord,V> Container for TreeMap<K, V> {
     pure fn is_empty(&self) -> bool { self.root.is_none() }
 }
 
-impl<K:Ord,V> Mutable for TreeMap<K, V> {
+impl<K: TotalOrd, V> Mutable for TreeMap<K, V> {
     /// Clear the map, removing all key-value pairs.
     fn clear(&mut self) {
         self.root = None;
@@ -128,7 +125,7 @@ impl<K:Ord,V> Mutable for TreeMap<K, V> {
     }
 }
 
-impl<K:Ord,V> Map<K, V> for TreeMap<K, V> {
+impl<K: TotalOrd, V> Map<K, V> for TreeMap<K, V> {
     /// Return true if the map contains a value for the specified key
     pure fn contains_key(&self, key: &K) -> bool {
         self.find(key).is_some()
@@ -146,12 +143,10 @@ impl<K:Ord,V> Map<K, V> for TreeMap<K, V> {
         loop {
             match *current {
               Some(ref r) => {
-                if *key < r.key {
-                    current = &r.left;
-                } else if r.key < *key {
-                    current = &r.right;
-                } else {
-                    return Some(&r.value);
+                match key.cmp(&r.key) {
+                   Less => current = &r.left,
+                   Greater => current = &r.right,
+                   Equal => return Some(&r.value)
                 }
               }
               None => return None
@@ -177,7 +172,7 @@ impl<K:Ord,V> Map<K, V> for TreeMap<K, V> {
     }
 }
 
-pub impl <K:Ord,V> TreeMap<K, V> {
+pub impl<K: TotalOrd, V> TreeMap<K, V> {
     /// Create an empty TreeMap
     static pure fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
 
@@ -207,7 +202,7 @@ pub struct TreeMapIterator<K, V> {
 /// Advance the iterator to the next node (in order) and return a
 /// tuple with a reference to the key and value. If there are no
 /// more nodes, return `None`.
-pub fn map_next<K: Ord, V>(iter: &mut TreeMapIterator/&r<K, V>)
+pub fn map_next<K, V>(iter: &mut TreeMapIterator/&r<K, V>)
                         -> Option<(&r/K, &r/V)> {
     while !iter.stack.is_empty() || iter.node.is_some() {
         match *iter.node {
@@ -226,8 +221,8 @@ pub fn map_next<K: Ord, V>(iter: &mut TreeMapIterator/&r<K, V>)
 }
 
 /// Advance the iterator through the map
-pub fn map_advance<K: Ord, V>(iter: &mut TreeMapIterator/&r<K, V>,
-                          f: fn((&r/K, &r/V)) -> bool) {
+pub fn map_advance<K, V>(iter: &mut TreeMapIterator/&r<K, V>,
+                         f: fn((&r/K, &r/V)) -> bool) {
     loop {
         match map_next(iter) {
           Some(x) => {
@@ -242,25 +237,25 @@ pub struct TreeSet<T> {
     priv map: TreeMap<T, ()>
 }
 
-impl<T:Ord> BaseIter<T> for TreeSet<T> {
+impl<T: TotalOrd> BaseIter<T> for TreeSet<T> {
     /// Visit all values in order
     pure fn each(&self, f: fn(&T) -> bool) { self.map.each_key(f) }
     pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
 }
 
-impl<T:Ord> ReverseIter<T> for TreeSet<T> {
+impl<T: TotalOrd> ReverseIter<T> for TreeSet<T> {
     /// Visit all values in reverse order
     pure fn each_reverse(&self, f: fn(&T) -> bool) {
         self.map.each_key_reverse(f)
     }
 }
 
-impl<T:Eq + Ord> Eq for TreeSet<T> {
+impl<T: Eq + TotalOrd> Eq for TreeSet<T> {
     pure fn eq(&self, other: &TreeSet<T>) -> bool { self.map == other.map }
     pure fn ne(&self, other: &TreeSet<T>) -> bool { self.map != other.map }
 }
 
-impl<T:Ord> Ord for TreeSet<T> {
+impl<T: Ord + TotalOrd> Ord for TreeSet<T> {
     #[inline(always)]
     pure fn lt(&self, other: &TreeSet<T>) -> bool { self.map < other.map }
     #[inline(always)]
@@ -271,7 +266,7 @@ impl<T:Ord> Ord for TreeSet<T> {
     pure fn gt(&self, other: &TreeSet<T>) -> bool { self.map > other.map }
 }
 
-impl<T:Ord> Container for TreeSet<T> {
+impl<T: TotalOrd> Container for TreeSet<T> {
     /// Return the number of elements in the set
     pure fn len(&self) -> uint { self.map.len() }
 
@@ -279,12 +274,12 @@ impl<T:Ord> Container for TreeSet<T> {
     pure fn is_empty(&self) -> bool { self.map.is_empty() }
 }
 
-impl<T:Ord> Mutable for TreeSet<T> {
+impl<T: TotalOrd> Mutable for TreeSet<T> {
     /// Clear the set, removing all values.
     fn clear(&mut self) { self.map.clear() }
 }
 
-impl<T:Ord> Set<T> for TreeSet<T> {
+impl<T: TotalOrd> Set<T> for TreeSet<T> {
     /// Return true if the set contains a value
     pure fn contains(&self, value: &T) -> bool {
         self.map.contains_key(value)
@@ -309,12 +304,10 @@ impl<T:Ord> Set<T> for TreeSet<T> {
             while a.is_some() && b.is_some() {
                 let a1 = a.unwrap();
                 let b1 = b.unwrap();
-                if a1 < b1 {
-                    a = set_next(&mut x);
-                } else if b1 < a1 {
-                    b = set_next(&mut y);
-                } else {
-                    return false;
+                match a1.cmp(b1) {
+                  Less => a = set_next(&mut x),
+                  Greater => b = set_next(&mut y),
+                  Equal => return false
                 }
             }
         }
@@ -341,13 +334,12 @@ impl<T:Ord> Set<T> for TreeSet<T> {
                 let a1 = a.unwrap();
                 let b1 = b.unwrap();
 
-                if b1 < a1 {
-                    return false
+                match a1.cmp(b1) {
+                  Less => (),
+                  Greater => return false,
+                  Equal => b = set_next(&mut y),
                 }
 
-                if !(a1 < b1) {
-                    b = set_next(&mut y);
-                }
                 a = set_next(&mut x);
             }
         }
@@ -373,11 +365,13 @@ impl<T:Ord> Set<T> for TreeSet<T> {
                 let a1 = a.unwrap();
                 let b1 = b.unwrap();
 
-                if a1 < b1 {
+                let cmp = a1.cmp(b1);
+
+                if cmp == Less {
                     if !f(a1) { return }
                     a = set_next(&mut x);
                 } else {
-                    if !(b1 < a1) { a = set_next(&mut x) }
+                    if cmp == Equal { a = set_next(&mut x) }
                     b = set_next(&mut y);
                 }
             }
@@ -404,11 +398,13 @@ impl<T:Ord> Set<T> for TreeSet<T> {
                 let a1 = a.unwrap();
                 let b1 = b.unwrap();
 
-                if a1 < b1 {
+                let cmp = a1.cmp(b1);
+
+                if cmp == Less {
                     if !f(a1) { return }
                     a = set_next(&mut x);
                 } else {
-                    if b1 < a1 {
+                    if cmp == Greater {
                         if !f(b1) { return }
                     } else {
                         a = set_next(&mut x);
@@ -434,10 +430,13 @@ impl<T:Ord> Set<T> for TreeSet<T> {
             while a.is_some() && b.is_some() {
                 let a1 = a.unwrap();
                 let b1 = b.unwrap();
-                if a1 < b1 {
+
+                let cmp = a1.cmp(b1);
+
+                if cmp == Less {
                     a = set_next(&mut x);
                 } else {
-                    if !(b1 < a1) {
+                    if cmp == Equal {
                         if !f(a1) { return }
                     }
                     b = set_next(&mut y);
@@ -465,12 +464,14 @@ impl<T:Ord> Set<T> for TreeSet<T> {
                 let a1 = a.unwrap();
                 let b1 = b.unwrap();
 
-                if b1 < a1 {
+                let cmp = a1.cmp(b1);
+
+                if cmp == Greater {
                     if !f(b1) { return }
                     b = set_next(&mut y);
                 } else {
                     if !f(a1) { return }
-                    if !(a1 < b1) {
+                    if cmp == Equal {
                         b = set_next(&mut y);
                     }
                     a = set_next(&mut x);
@@ -480,7 +481,7 @@ impl<T:Ord> Set<T> for TreeSet<T> {
     }
 }
 
-pub impl <T:Ord> TreeSet<T> {
+pub impl <T: TotalOrd> TreeSet<T> {
     /// Create an empty TreeSet
     static pure fn new() -> TreeSet<T> { TreeSet{map: TreeMap::new()} }
 
@@ -498,12 +499,12 @@ pub struct TreeSetIterator<T> {
 
 /// Advance the iterator to the next node (in order). If this iterator is
 /// finished, does nothing.
-pub fn set_next<T: Ord>(iter: &mut TreeSetIterator/&r<T>) -> Option<&r/T> {
+pub fn set_next<T>(iter: &mut TreeSetIterator/&r<T>) -> Option<&r/T> {
     do map_next(&mut iter.iter).map |&(value, _)| { value }
 }
 
 /// Advance the iterator through the set
-fn set_advance<T: Ord>(iter: &mut TreeSetIterator/&r<T>,
+fn set_advance<T>(iter: &mut TreeSetIterator/&r<T>,
                        f: fn(&r/T) -> bool) {
     do map_advance(&mut iter.iter) |(k, _)| { f(k) }
 }
@@ -518,14 +519,14 @@ struct TreeNode<K, V> {
     level: uint
 }
 
-pub impl <K:Ord,V> TreeNode<K, V> {
+pub impl<K: TotalOrd, V> TreeNode<K, V> {
     #[inline(always)]
     static pure fn new(key: K, value: V) -> TreeNode<K, V> {
         TreeNode{key: key, value: value, left: None, right: None, level: 1}
     }
 }
 
-pure fn each<K:Ord,V>(node: &r/Option<~TreeNode<K, V>>,
+pure fn each<K: TotalOrd, V>(node: &r/Option<~TreeNode<K, V>>,
                         f: fn(&(&r/K, &r/V)) -> bool) {
     do node.iter |x| {
         each(&x.left, f);
@@ -533,7 +534,7 @@ pure fn each<K:Ord,V>(node: &r/Option<~TreeNode<K, V>>,
     }
 }
 
-pure fn each_reverse<K:Ord,V>(node: &r/Option<~TreeNode<K, V>>,
+pure fn each_reverse<K: TotalOrd, V>(node: &r/Option<~TreeNode<K, V>>,
                                 f: fn(&(&r/K, &r/V)) -> bool) {
     do node.iter |x| {
         each_reverse(&x.right, f);
@@ -542,7 +543,7 @@ pure fn each_reverse<K:Ord,V>(node: &r/Option<~TreeNode<K, V>>,
 }
 
 // Remove left horizontal link by rotating right
-fn skew<K:Ord,V>(node: &mut ~TreeNode<K, V>) {
+fn skew<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
     if node.left.map_default(false, |x| x.level == node.level) {
         let mut save = node.left.swap_unwrap();
         node.left <-> save.right; // save.right now None
@@ -553,7 +554,7 @@ fn skew<K:Ord,V>(node: &mut ~TreeNode<K, V>) {
 
 // Remove dual horizontal link by rotating left and increasing level of
 // the parent
-fn split<K:Ord,V>(node: &mut ~TreeNode<K, V>) {
+fn split<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
     if node.right.map_default(false,
       |x| x.right.map_default(false, |y| y.level == node.level)) {
         let mut save = node.right.swap_unwrap();
@@ -564,24 +565,28 @@ fn split<K:Ord,V>(node: &mut ~TreeNode<K, V>) {
     }
 }
 
-fn insert<K:Ord,V>(node: &mut Option<~TreeNode<K, V>>, key: K,
-                     value: V) -> bool {
+fn insert<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>, key: K,
+                          value: V) -> bool {
     match *node {
       Some(ref mut save) => {
-        if key < save.key {
+        match key.cmp(&save.key) {
+          Less => {
             let inserted = insert(&mut save.left, key, value);
             skew(save);
             split(save);
             inserted
-        } else if save.key < key {
+          }
+          Greater => {
             let inserted = insert(&mut save.right, key, value);
             skew(save);
             split(save);
             inserted
-        } else {
+          }
+          Equal => {
             save.key = key;
             save.value = value;
             false
+          }
         }
       }
       None => {
@@ -591,8 +596,9 @@ fn insert<K:Ord,V>(node: &mut Option<~TreeNode<K, V>>, key: K,
     }
 }
 
-fn remove<K:Ord,V>(node: &mut Option<~TreeNode<K, V>>, key: &K) -> bool {
-    fn heir_swap<K:Ord,V>(node: &mut ~TreeNode<K, V>,
+fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
+                          key: &K) -> bool {
+    fn heir_swap<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>,
                             child: &mut Option<~TreeNode<K, V>>) {
         // *could* be done without recursion, but it won't borrow check
         do child.mutate |mut child| {
@@ -611,11 +617,10 @@ fn remove<K:Ord,V>(node: &mut Option<~TreeNode<K, V>>, key: &K) -> bool {
         return false // bottom of tree
       }
       Some(ref mut save) => {
-        let (removed, this) = if save.key < *key {
-            (remove(&mut save.right, key), false)
-        } else if *key < save.key {
-            (remove(&mut save.left, key), false)
-        } else {
+        let (removed, this) = match key.cmp(&save.key) {
+          Less => (remove(&mut save.left, key), false),
+          Greater => (remove(&mut save.right, key), false),
+          Equal => {
             if save.left.is_some() {
                 if save.right.is_some() {
                     let mut left = save.left.swap_unwrap();
@@ -637,6 +642,7 @@ fn remove<K:Ord,V>(node: &mut Option<~TreeNode<K, V>>, key: &K) -> bool {
             } else {
                 (true, true)
             }
+          }
         };
 
         if !this {
@@ -682,12 +688,9 @@ fn remove<K:Ord,V>(node: &mut Option<~TreeNode<K, V>>, key: &K) -> bool {
 
 #[cfg(test)]
 mod test_treemap {
+    use core::prelude::*;
     use super::*;
-    use core::cmp::{Ord, Eq};
-    use core::option::{Some, Option, None};
     use core::rand;
-    use core::str;
-    use core::vec;
 
     #[test]
     fn find_empty() {
@@ -742,7 +745,8 @@ mod test_treemap {
         assert m.find(&k1) == Some(&v1);
     }
 
-    fn check_equal<K:Eq + Ord,V:Eq>(ctrl: &[(K, V)], map: &TreeMap<K, V>) {
+    fn check_equal<K: Eq + TotalOrd, V: Eq>(ctrl: &[(K, V)],
+                                            map: &TreeMap<K, V>) {
         assert ctrl.is_empty() == map.is_empty();
         for ctrl.each |x| {
             let &(k, v) = x;
@@ -762,11 +766,11 @@ mod test_treemap {
         }
     }
 
-    fn check_left<K:Ord,V>(node: &Option<~TreeNode<K, V>>,
-                             parent: &~TreeNode<K, V>) {
+    fn check_left<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
+                                  parent: &~TreeNode<K, V>) {
         match *node {
           Some(ref r) => {
-            assert r.key < parent.key;
+            assert r.key.cmp(&parent.key) == Less;
             assert r.level == parent.level - 1; // left is black
             check_left(&r.left, r);
             check_right(&r.right, r, false);
@@ -775,11 +779,12 @@ mod test_treemap {
         }
     }
 
-    fn check_right<K:Ord,V>(node: &Option<~TreeNode<K, V>>,
-                              parent: &~TreeNode<K, V>, parent_red: bool) {
+    fn check_right<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
+                                   parent: &~TreeNode<K, V>,
+                                   parent_red: bool) {
         match *node {
           Some(ref r) => {
-            assert r.key > parent.key;
+            assert r.key.cmp(&parent.key) == Greater;
             let red = r.level == parent.level;
             if parent_red { assert !red } // no dual horizontal links
             assert red || r.level == parent.level - 1; // right red or black
@@ -790,7 +795,7 @@ mod test_treemap {
         }
     }
 
-    fn check_structure<K:Ord,V>(map: &TreeMap<K, V>) {
+    fn check_structure<K: TotalOrd, V>(map: &TreeMap<K, V>) {
         match map.root {
           Some(ref r) => {
             check_left(&r.left, r);