diff options
| author | blake2-ppc <blake2-ppc> | 2013-08-08 22:07:22 +0200 |
|---|---|---|
| committer | blake2-ppc <blake2-ppc> | 2013-08-08 22:07:22 +0200 |
| commit | 5dde29c947ec1e6b0a52c7f3ccb0771d2a7736f4 (patch) | |
| tree | a909e87fc09de83c9400c38116a9a7e47c7c7d71 /src/libstd | |
| parent | 86da55e85b1f1dd520111b52d1f76c61ea43b382 (diff) | |
| download | rust-5dde29c947ec1e6b0a52c7f3ccb0771d2a7736f4.tar.gz rust-5dde29c947ec1e6b0a52c7f3ccb0771d2a7736f4.zip | |
std: Fix tuple lexicographical order
Use the definition, where R is <, <=, >=, or >
[x, ..xs] R [y, ..ys] = if x != y { x R y } else { xs R ys }
Previously, tuples would only implement < and derive the other
comparisons from it; this is incorrect. Included are several testcases
involving NaN comparisons that are now correct.
Previously, tuples would consider an element equal if both a < b and
b < a were false, this was also incorrect.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/tuple.rs | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 3dc7f65b3ad..238b14ed554 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -197,17 +197,23 @@ macro_rules! tuple_impls { } #[cfg(not(test))] - impl<$($T:Ord),+> Ord for ($($T,)+) { + impl<$($T:Ord + Eq),+> Ord for ($($T,)+) { #[inline] fn lt(&self, other: &($($T,)+)) -> bool { - lexical_lt!($(self.$get_ref_fn(), other.$get_ref_fn()),+) + lexical_ord!(lt, $(self.$get_ref_fn(), other.$get_ref_fn()),+) } #[inline] - fn le(&self, other: &($($T,)+)) -> bool { !(*other).lt(&(*self)) } + fn le(&self, other: &($($T,)+)) -> bool { + lexical_ord!(le, $(self.$get_ref_fn(), other.$get_ref_fn()),+) + } #[inline] - fn ge(&self, other: &($($T,)+)) -> bool { !(*self).lt(other) } + fn ge(&self, other: &($($T,)+)) -> bool { + lexical_ord!(ge, $(self.$get_ref_fn(), other.$get_ref_fn()),+) + } #[inline] - fn gt(&self, other: &($($T,)+)) -> bool { (*other).lt(&(*self)) } + fn gt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(gt, $(self.$get_ref_fn(), other.$get_ref_fn()),+) + } } #[cfg(not(test))] @@ -234,17 +240,16 @@ macro_rules! tuple_impls { } } -// Constructs an expression that performs a lexical less-than -// ordering. The values are interleaved, so the macro invocation for -// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_lt!(a1, b1, a2, b2, +// Constructs an expression that performs a lexical ordering using method $rel. +// The values are interleaved, so the macro invocation for +// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2, // a3, b3)` (and similarly for `lexical_cmp`) -macro_rules! lexical_lt { - ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { - if *$a < *$b { true } - else if !(*$b < *$a) { lexical_lt!($($rest_a, $rest_b),+) } - else { false } +macro_rules! lexical_ord { + ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + if *$a != *$b { lexical_ord!($rel, $a, $b) } + else { lexical_ord!($rel, $($rest_a, $rest_b),+) } }; - ($a:expr, $b:expr) => { *$a < *$b }; + ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) }; } macro_rules! lexical_cmp { @@ -436,6 +441,8 @@ mod tests { fn test_tuple_cmp() { let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u)); + let nan = 0.0/0.0; + // Eq assert_eq!(small, small); assert_eq!(big, big); @@ -456,6 +463,13 @@ mod tests { assert!(big >= small); assert!(big >= big); + assert!(!((1.0, 2.0) < (nan, 3.0))); + assert!(!((1.0, 2.0) <= (nan, 3.0))); + assert!(!((1.0, 2.0) > (nan, 3.0))); + assert!(!((1.0, 2.0) >= (nan, 3.0))); + assert!(((1.0, 2.0) < (2.0, nan))); + assert!(!((2.0, 2.0) < (2.0, nan))); + // TotalEq assert!(small.equals(&small)); assert!(big.equals(&big)); |
