diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cc396455..62bfd0d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- minf +- fmin +- fmaxf +- fmax + ## [v0.1.2] - 2018-07-18 ### Added diff --git a/src/lib.rs b/src/lib.rs index 0d0f6155a..df3c8cf60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,6 +136,10 @@ pub trait F32Ext: private::Sealed + Sized { fn acosh(self) -> Self; fn atanh(self) -> Self; + + fn min(self, other: Self) -> Self; + + fn max(self, other: Self) -> Self; } impl F32Ext for f32 { @@ -327,6 +331,16 @@ impl F32Ext for f32 { fn atanh(self) -> Self { atanhf(self) } + + #[inline] + fn min(self, other: Self) -> Self { + fminf(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + fmaxf(self, other) + } } /// Math support for `f64` @@ -410,6 +424,10 @@ pub trait F64Ext: private::Sealed + Sized { fn acosh(self) -> Self; fn atanh(self) -> Self; + + fn min(self, other: Self) -> Self; + + fn max(self, other: Self) -> Self; } impl F64Ext for f64 { @@ -601,6 +619,16 @@ impl F64Ext for f64 { fn atanh(self) -> Self { atanh(self) } + + #[inline] + fn min(self, other: Self) -> Self { + fmin(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + fmax(self, other) + } } mod private { diff --git a/src/math/fmax.rs b/src/math/fmax.rs new file mode 100644 index 000000000..22016d11c --- /dev/null +++ b/src/math/fmax.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmax(x: f64, y: f64) -> f64 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if x.is_nan() || x < y { y } else { x }) * 1.0 +} diff --git a/src/math/fmaxf.rs b/src/math/fmaxf.rs new file mode 100644 index 000000000..a883fdaef --- /dev/null +++ b/src/math/fmaxf.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmaxf(x: f32, y: f32) -> f32 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if x.is_nan() || x < y { y } else { x }) * 1.0 +} diff --git a/src/math/fmin.rs b/src/math/fmin.rs new file mode 100644 index 000000000..d1ccc3a46 --- /dev/null +++ b/src/math/fmin.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmin(x: f64, y: f64) -> f64 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if y.is_nan() || x < y { x } else { y }) * 1.0 +} diff --git a/src/math/fminf.rs b/src/math/fminf.rs new file mode 100644 index 000000000..43ec97cb5 --- /dev/null +++ b/src/math/fminf.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fminf(x: f32, y: f32) -> f32 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if y.is_nan() || x < y { x } else { y }) * 1.0 +} diff --git a/src/math/mod.rs b/src/math/mod.rs index c4d247414..35ffe1a2c 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -112,6 +112,10 @@ mod floor; mod floorf; mod fma; mod fmaf; +mod fmax; +mod fmaxf; +mod fmin; +mod fminf; mod fmod; mod fmodf; mod frexp; @@ -212,6 +216,10 @@ pub use self::floor::floor; pub use self::floorf::floorf; pub use self::fma::fma; pub use self::fmaf::fmaf; +pub use self::fmax::fmax; +pub use self::fmaxf::fmaxf; +pub use self::fmin::fmin; +pub use self::fminf::fminf; pub use self::fmod::fmod; pub use self::fmodf::fmodf; pub use self::frexp::frexp;