diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 97ad23696bdab..ada47fb597e5d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -225,16 +225,26 @@ impl Ord for f32 { } impl Orderable for f32 { + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] - fn min(&self, other: &f32) -> f32 { fmin(*self, *other) } + fn min(&self, other: &f32) -> f32 { + if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) } + } + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] - fn max(&self, other: &f32) -> f32 { fmax(*self, *other) } + fn max(&self, other: &f32) -> f32 { + if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) } + } + /// Returns the number constrained within the range `mn <= self <= mx`. + /// If any of the numbers are `NaN` then `NaN` is returned. #[inline(always)] fn clamp(&self, mn: &f32, mx: &f32) -> f32 { - if *self > *mx { *mx } else - if *self < *mn { *mn } else { *self } + if self.is_NaN() { *self } + else if !(*self <= *mx) { *mx } + else if !(*self >= *mn) { *mn } + else { *self } } } @@ -828,14 +838,25 @@ mod tests { } #[test] - fn test_orderable() { + fn test_min() { assert_eq!(1f32.min(&2f32), 1f32); assert_eq!(2f32.min(&1f32), 1f32); + } + + #[test] + fn test_max() { assert_eq!(1f32.max(&2f32), 2f32); assert_eq!(2f32.max(&1f32), 2f32); + } + + #[test] + fn test_clamp() { assert_eq!(1f32.clamp(&2f32, &4f32), 2f32); assert_eq!(8f32.clamp(&2f32, &4f32), 4f32); assert_eq!(3f32.clamp(&2f32, &4f32), 3f32); + assert!(3f32.clamp(&Float::NaN::(), &4f32).is_NaN()); + assert!(3f32.clamp(&2f32, &Float::NaN::()).is_NaN()); + assert!(Float::NaN::().clamp(&2f32, &4f32).is_NaN()); } #[test] diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 92ce4969f47b8..07a29652e94aa 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -246,16 +246,26 @@ impl Ord for f64 { } impl Orderable for f64 { + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] - fn min(&self, other: &f64) -> f64 { fmin(*self, *other) } + fn min(&self, other: &f64) -> f64 { + if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) } + } + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] - fn max(&self, other: &f64) -> f64 { fmax(*self, *other) } + fn max(&self, other: &f64) -> f64 { + if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) } + } + /// Returns the number constrained within the range `mn <= self <= mx`. + /// If any of the numbers are `NaN` then `NaN` is returned. #[inline(always)] fn clamp(&self, mn: &f64, mx: &f64) -> f64 { - if *self > *mx { *mx } else - if *self < *mn { *mn } else { *self } + if self.is_NaN() { *self } + else if !(*self <= *mx) { *mx } + else if !(*self >= *mn) { *mn } + else { *self } } } @@ -869,14 +879,29 @@ mod tests { } #[test] - fn test_orderable() { + fn test_min() { assert_eq!(1f64.min(&2f64), 1f64); assert_eq!(2f64.min(&1f64), 1f64); + assert!(1f64.min(&Float::NaN::()).is_NaN()); + assert!(Float::NaN::().min(&1f64).is_NaN()); + } + + #[test] + fn test_max() { assert_eq!(1f64.max(&2f64), 2f64); assert_eq!(2f64.max(&1f64), 2f64); + assert!(1f64.max(&Float::NaN::()).is_NaN()); + assert!(Float::NaN::().max(&1f64).is_NaN()); + } + + #[test] + fn test_clamp() { assert_eq!(1f64.clamp(&2f64, &4f64), 2f64); assert_eq!(8f64.clamp(&2f64, &4f64), 4f64); assert_eq!(3f64.clamp(&2f64, &4f64), 3f64); + assert!(3f64.clamp(&Float::NaN::(), &4f64).is_NaN()); + assert!(3f64.clamp(&2f64, &Float::NaN::()).is_NaN()); + assert!(Float::NaN::().clamp(&2f64, &4f64).is_NaN()); } #[test] diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index d784aeb23971c..ef0adee884b7c 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -385,20 +385,23 @@ impl Ord for float { } impl Orderable for float { + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] fn min(&self, other: &float) -> float { - fmin(*self as f64, *other as f64) as float + (*self as f64).min(&(*other as f64)) as float } + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] fn max(&self, other: &float) -> float { - fmax(*self as f64, *other as f64) as float + (*self as f64).max(&(*other as f64)) as float } + /// Returns the number constrained within the range `mn <= self <= mx`. + /// If any of the numbers are `NaN` then `NaN` is returned. #[inline(always)] fn clamp(&self, mn: &float, mx: &float) -> float { - if *self > *mx { *mx } else - if *self < *mn { *mn } else { *self } + (*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float } } @@ -802,14 +805,25 @@ mod tests { } #[test] - fn test_orderable() { + fn test_min() { assert_eq!(1f.min(&2f), 1f); assert_eq!(2f.min(&1f), 1f); + } + + #[test] + fn test_max() { assert_eq!(1f.max(&2f), 2f); assert_eq!(2f.max(&1f), 2f); + } + + #[test] + fn test_clamp() { assert_eq!(1f.clamp(&2f, &4f), 2f); assert_eq!(8f.clamp(&2f, &4f), 4f); assert_eq!(3f.clamp(&2f, &4f), 3f); + assert!(3f.clamp(&Float::NaN::(), &4f).is_NaN()); + assert!(3f.clamp(&2f, &Float::NaN::()).is_NaN()); + assert!(Float::NaN::().clamp(&2f, &4f).is_NaN()); } #[test]