Skip to content

add a TotalOrd trait and reimplement TreeMap with it #5196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
}
}
4 changes: 2 additions & 2 deletions src/libcore/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
40 changes: 39 additions & 1 deletion src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -2382,6 +2411,7 @@ mod tests {
use ptr;
use str::*;
use vec;
use cmp::{TotalOrd, Less, Equal, Greater};

#[test]
fn test_eq() {
Expand Down Expand Up @@ -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;
}
}
59 changes: 50 additions & 9 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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]) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -2429,6 +2461,7 @@ mod tests {
use option;
use sys;
use vec::*;
use cmp::*;

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

Expand Down Expand Up @@ -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:
Expand Down
Loading