Skip to content

Commit 2304fe6

Browse files
committed
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.
2 parents 5aca7d6 + 035233a commit 2304fe6

File tree

5 files changed

+253
-93
lines changed

5 files changed

+253
-93
lines changed

src/libcore/cmp.rs

+76
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,70 @@ pub trait Eq {
3737
pure fn ne(&self, other: &Self) -> bool;
3838
}
3939

40+
#[deriving_eq]
41+
pub enum Ordering { Less, Equal, Greater }
42+
43+
/// Trait for types that form a total order
44+
pub trait TotalOrd {
45+
pure fn cmp(&self, other: &Self) -> Ordering;
46+
}
47+
48+
pure fn icmp<T: Ord>(a: &T, b: &T) -> Ordering {
49+
if *a < *b { Less }
50+
else if *a > *b { Greater }
51+
else { Equal }
52+
}
53+
54+
impl TotalOrd for u8 {
55+
#[inline(always)]
56+
pure fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) }
57+
}
58+
59+
impl TotalOrd for u16 {
60+
#[inline(always)]
61+
pure fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) }
62+
}
63+
64+
impl TotalOrd for u32 {
65+
#[inline(always)]
66+
pure fn cmp(&self, other: &u32) -> Ordering { icmp(self, other) }
67+
}
68+
69+
impl TotalOrd for u64 {
70+
#[inline(always)]
71+
pure fn cmp(&self, other: &u64) -> Ordering { icmp(self, other) }
72+
}
73+
74+
impl TotalOrd for i8 {
75+
#[inline(always)]
76+
pure fn cmp(&self, other: &i8) -> Ordering { icmp(self, other) }
77+
}
78+
79+
impl TotalOrd for i16 {
80+
#[inline(always)]
81+
pure fn cmp(&self, other: &i16) -> Ordering { icmp(self, other) }
82+
}
83+
84+
impl TotalOrd for i32 {
85+
#[inline(always)]
86+
pure fn cmp(&self, other: &i32) -> Ordering { icmp(self, other) }
87+
}
88+
89+
impl TotalOrd for i64 {
90+
#[inline(always)]
91+
pure fn cmp(&self, other: &i64) -> Ordering { icmp(self, other) }
92+
}
93+
94+
impl TotalOrd for int {
95+
#[inline(always)]
96+
pure fn cmp(&self, other: &int) -> Ordering { icmp(self, other) }
97+
}
98+
99+
impl TotalOrd for uint {
100+
#[inline(always)]
101+
pure fn cmp(&self, other: &uint) -> Ordering { icmp(self, other) }
102+
}
103+
40104
/**
41105
* Trait for values that can be compared for a sort-order.
42106
*
@@ -94,3 +158,15 @@ pub pure fn min<T:Ord>(v1: T, v2: T) -> T {
94158
pub pure fn max<T:Ord>(v1: T, v2: T) -> T {
95159
if v1 > v2 { v1 } else { v2 }
96160
}
161+
162+
#[cfg(test)]
163+
mod test {
164+
#[test]
165+
fn test_int() {
166+
assert 5.cmp(&10) == Less;
167+
assert 10.cmp(&5) == Greater;
168+
assert 5.cmp(&5) == Equal;
169+
assert (-5).cmp(&12) == Less;
170+
assert 12.cmp(-5) == Greater;
171+
}
172+
}

src/libcore/prelude.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ pub use result::{Result, Ok, Err};
2424
/* Reexported types and traits */
2525

2626
pub use clone::Clone;
27-
pub use cmp::{Eq, Ord};
27+
pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
2828
pub use container::{Container, Mutable, Map, Set};
2929
pub use hash::Hash;
30-
pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
30+
pub use iter::{BaseIter, ReverseIter, ExtendedIter, EqIter, CopyableIter};
3131
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
3232
pub use num::NumCast;
3333
pub use path::GenericPath;

src/libcore/str.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
use at_vec;
2121
use cast;
2222
use char;
23-
use cmp::{Eq, Ord};
23+
use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
2424
use libc;
2525
use libc::size_t;
2626
use io::WriterUtil;
@@ -773,6 +773,35 @@ pub pure fn eq(a: &~str, b: &~str) -> bool {
773773
eq_slice(*a, *b)
774774
}
775775

776+
pure fn cmp(a: &str, b: &str) -> Ordering {
777+
let low = uint::min(a.len(), b.len());
778+
779+
for uint::range(0, low) |idx| {
780+
match a[idx].cmp(&b[idx]) {
781+
Greater => return Greater,
782+
Less => return Less,
783+
Equal => ()
784+
}
785+
}
786+
787+
a.len().cmp(&b.len())
788+
}
789+
790+
#[cfg(notest)]
791+
impl TotalOrd for &str {
792+
pure fn cmp(&self, other: & &self/str) -> Ordering { cmp(*self, *other) }
793+
}
794+
795+
#[cfg(notest)]
796+
impl TotalOrd for ~str {
797+
pure fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) }
798+
}
799+
800+
#[cfg(notest)]
801+
impl TotalOrd for @str {
802+
pure fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) }
803+
}
804+
776805
/// Bytewise slice less than
777806
pure fn lt(a: &str, b: &str) -> bool {
778807
let (a_len, b_len) = (a.len(), b.len());
@@ -2389,6 +2418,7 @@ mod tests {
23892418
use ptr;
23902419
use str::*;
23912420
use vec;
2421+
use cmp::{TotalOrd, Less, Equal, Greater};
23922422

23932423
#[test]
23942424
fn test_eq() {
@@ -3395,4 +3425,12 @@ mod tests {
33953425
assert view("abcdef", 1, 5).to_managed() == @"bcde";
33963426
}
33973427
3428+
#[test]
3429+
fn test_total_ord() {
3430+
"1234".cmp(& &"123") == Greater;
3431+
"123".cmp(& &"1234") == Less;
3432+
"1234".cmp(& &"1234") == Equal;
3433+
"12345555".cmp(& &"123456") == Less;
3434+
"22".cmp(& &"1234") == Greater;
3435+
}
33983436
}

src/libcore/vec.rs

+50-9
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use container::{Container, Mutable};
1616
use cast::transmute;
1717
use cast;
18-
use cmp::{Eq, Ord};
18+
use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
1919
use iter::BaseIter;
2020
use iter;
2121
use kinds::Copy;
@@ -1425,7 +1425,7 @@ pub pure fn rev_eachi<T>(v: &r/[T], blk: fn(i: uint, v: &r/T) -> bool) {
14251425
* Both vectors must have the same length
14261426
*/
14271427
#[inline]
1428-
pub fn each2<U, T>(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) {
1428+
pub pure fn each2<U, T>(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) {
14291429
assert len(v1) == len(v2);
14301430
for uint::range(0u, len(v1)) |i| {
14311431
if !f(&v1[i], &v2[i]) {
@@ -1575,6 +1575,38 @@ impl<T:Eq> Eq for @[T] {
15751575

15761576
// Lexicographical comparison
15771577

1578+
pure fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering {
1579+
let low = uint::min(a.len(), b.len());
1580+
1581+
for uint::range(0, low) |idx| {
1582+
match a[idx].cmp(&b[idx]) {
1583+
Greater => return Greater,
1584+
Less => return Less,
1585+
Equal => ()
1586+
}
1587+
}
1588+
1589+
a.len().cmp(&b.len())
1590+
}
1591+
1592+
#[cfg(notest)]
1593+
impl<T: TotalOrd> TotalOrd for &[T] {
1594+
#[inline(always)]
1595+
pure fn cmp(&self, other: & &self/[T]) -> Ordering { cmp(*self, *other) }
1596+
}
1597+
1598+
#[cfg(notest)]
1599+
impl<T: TotalOrd> TotalOrd for ~[T] {
1600+
#[inline(always)]
1601+
pure fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) }
1602+
}
1603+
1604+
#[cfg(notest)]
1605+
impl<T: TotalOrd> TotalOrd for @[T] {
1606+
#[inline(always)]
1607+
pure fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) }
1608+
}
1609+
15781610
pure fn lt<T:Ord>(a: &[T], b: &[T]) -> bool {
15791611
let (a_len, b_len) = (a.len(), b.len());
15801612
let mut end = uint::min(a_len, b_len);
@@ -2151,7 +2183,7 @@ pub mod bytes {
21512183
use vec;
21522184

21532185
/// Bytewise string comparison
2154-
pub pure fn cmp(a: &~[u8], b: &~[u8]) -> int {
2186+
pub pure fn memcmp(a: &~[u8], b: &~[u8]) -> int {
21552187
let a_len = len(*a);
21562188
let b_len = len(*b);
21572189
let n = uint::min(a_len, b_len) as libc::size_t;
@@ -2172,22 +2204,22 @@ pub mod bytes {
21722204
}
21732205

21742206
/// Bytewise less than or equal
2175-
pub pure fn lt(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) < 0 }
2207+
pub pure fn lt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) < 0 }
21762208

21772209
/// Bytewise less than or equal
2178-
pub pure fn le(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) <= 0 }
2210+
pub pure fn le(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) <= 0 }
21792211

21802212
/// Bytewise equality
2181-
pub pure fn eq(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) == 0 }
2213+
pub pure fn eq(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) == 0 }
21822214

21832215
/// Bytewise inequality
2184-
pub pure fn ne(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) != 0 }
2216+
pub pure fn ne(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) != 0 }
21852217

21862218
/// Bytewise greater than or equal
2187-
pub pure fn ge(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) >= 0 }
2219+
pub pure fn ge(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) >= 0 }
21882220

21892221
/// Bytewise greater than
2190-
pub pure fn gt(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) > 0 }
2222+
pub pure fn gt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) > 0 }
21912223

21922224
/**
21932225
* Copies data from one vector to another.
@@ -2429,6 +2461,7 @@ mod tests {
24292461
use option;
24302462
use sys;
24312463
use vec::*;
2464+
use cmp::*;
24322465

24332466
fn square(n: uint) -> uint { return n * n; }
24342467

@@ -3942,6 +3975,14 @@ mod tests {
39423975
}
39433976
}
39443977

3978+
#[test]
3979+
fn test_total_ord() {
3980+
[1, 2, 3, 4].cmp(& &[1, 2, 3]) == Greater;
3981+
[1, 2, 3].cmp(& &[1, 2, 3, 4]) == Less;
3982+
[1, 2, 3, 4].cmp(& &[1, 2, 3, 4]) == Equal;
3983+
[1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less;
3984+
[2, 2].cmp(& &[1, 2, 3, 4]) == Greater;
3985+
}
39453986
}
39463987

39473988
// Local Variables:

0 commit comments

Comments
 (0)