Propagate NaNs for Orderable methods impled on floating-point primitives
This commit is contained in:
parent
c9d099d60d
commit
9cdf402c80
@ -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::<f32>(), &4f32).is_NaN());
|
||||
assert!(3f32.clamp(&2f32, &Float::NaN::<f32>()).is_NaN());
|
||||
assert!(Float::NaN::<f32>().clamp(&2f32, &4f32).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -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::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().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::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().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::<f64>(), &4f64).is_NaN());
|
||||
assert!(3f64.clamp(&2f64, &Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().clamp(&2f64, &4f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -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::<float>(), &4f).is_NaN());
|
||||
assert!(3f.clamp(&2f, &Float::NaN::<float>()).is_NaN());
|
||||
assert!(Float::NaN::<float>().clamp(&2f, &4f).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user