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(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(v1: T, v2: T) -> T { pub pure fn max(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 d0a16f7875b..a7b4500c3e3 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -24,7 +24,7 @@ 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}; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 6ee6d282841..ef0fa9fc4e2 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()); @@ -2382,6 +2411,7 @@ mod tests { use ptr; use str::*; use vec; + use cmp::{TotalOrd, Less, Equal, Greater}; #[test] fn test_eq() { @@ -3388,4 +3418,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 4d28c769b18..86365247044 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(v: &r/[T], blk: fn(i: uint, v: &r/T) -> bool) { * Both vectors must have the same length */ #[inline] -pub fn each2(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) { +pub pure fn each2(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 Eq for @[T] { // Lexicographical comparison +pure fn cmp(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 TotalOrd for &[T] { + #[inline(always)] + pure fn cmp(&self, other: & &self/[T]) -> Ordering { cmp(*self, *other) } +} + +#[cfg(notest)] +impl TotalOrd for ~[T] { + #[inline(always)] + pure fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) } +} + +#[cfg(notest)] +impl TotalOrd for @[T] { + #[inline(always)] + pure fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) } +} + pure fn lt(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: