diff options
Diffstat (limited to 'src/f64/math.rs')
-rw-r--r-- | src/f64/math.rs | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/f64/math.rs b/src/f64/math.rs new file mode 100644 index 0000000..45ace5c --- /dev/null +++ b/src/f64/math.rs @@ -0,0 +1,215 @@ +#[cfg(feature = "libm")] +mod libm_math { + #[inline(always)] + pub(crate) fn abs(f: f64) -> f64 { + libm::fabs(f) + } + + #[inline(always)] + pub(crate) fn acos_approx(f: f64) -> f64 { + libm::acos(f.clamp(-1.0, 1.0)) + } + + #[inline(always)] + pub(crate) fn asin(f: f64) -> f64 { + libm::asin(f) + } + + #[inline(always)] + pub(crate) fn atan2(f: f64, other: f64) -> f64 { + libm::atan2(f, other) + } + + #[inline(always)] + pub(crate) fn sin(f: f64) -> f64 { + libm::sin(f) + } + + #[inline(always)] + pub(crate) fn sin_cos(f: f64) -> (f64, f64) { + libm::sincos(f) + } + + #[inline(always)] + pub(crate) fn tan(f: f64) -> f64 { + libm::tan(f) + } + + #[inline(always)] + pub(crate) fn sqrt(f: f64) -> f64 { + libm::sqrt(f) + } + + #[inline(always)] + pub(crate) fn copysign(f: f64, sign: f64) -> f64 { + libm::copysign(f, sign) + } + + #[inline(always)] + pub(crate) fn signum(f: f64) -> f64 { + if f.is_nan() { + f64::NAN + } else { + copysign(1.0, f) + } + } + + #[inline(always)] + pub(crate) fn round(f: f64) -> f64 { + libm::round(f) + } + + #[inline(always)] + pub(crate) fn trunc(f: f64) -> f64 { + libm::trunc(f) + } + + #[inline(always)] + pub(crate) fn ceil(f: f64) -> f64 { + libm::ceil(f) + } + + #[inline(always)] + pub(crate) fn floor(f: f64) -> f64 { + libm::floor(f) + } + + #[inline(always)] + pub(crate) fn exp(f: f64) -> f64 { + libm::exp(f) + } + + #[inline(always)] + pub(crate) fn powf(f: f64, n: f64) -> f64 { + libm::pow(f, n) + } + + #[inline(always)] + pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 { + libm::fma(a, b, c) + } + + #[inline] + pub fn div_euclid(a: f64, b: f64) -> f64 { + // Based on https://doc.rust-lang.org/src/std/f64.rs.html#293 + let q = libm::trunc(a / b); + if a % b < 0.0 { + return if b > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + pub fn rem_euclid(a: f64, b: f64) -> f64 { + let r = a % b; + if r < 0.0 { + r + abs(b) + } else { + r + } + } +} + +#[cfg(not(feature = "libm"))] +mod std_math { + #[inline(always)] + pub(crate) fn abs(f: f64) -> f64 { + f64::abs(f) + } + + #[inline(always)] + pub(crate) fn acos_approx(f: f64) -> f64 { + f64::acos(f64::clamp(f, -1.0, 1.0)) + } + + #[inline(always)] + pub(crate) fn asin(f: f64) -> f64 { + f64::asin(f) + } + + #[inline(always)] + pub(crate) fn atan2(f: f64, other: f64) -> f64 { + f64::atan2(f, other) + } + + #[inline(always)] + pub(crate) fn sin(f: f64) -> f64 { + f64::sin(f) + } + + #[inline(always)] + pub(crate) fn sin_cos(f: f64) -> (f64, f64) { + f64::sin_cos(f) + } + + #[inline(always)] + pub(crate) fn tan(f: f64) -> f64 { + f64::tan(f) + } + + #[inline(always)] + pub(crate) fn sqrt(f: f64) -> f64 { + f64::sqrt(f) + } + + #[inline(always)] + pub(crate) fn copysign(f: f64, sign: f64) -> f64 { + f64::copysign(f, sign) + } + + #[inline(always)] + pub(crate) fn signum(f: f64) -> f64 { + f64::signum(f) + } + + #[inline(always)] + pub(crate) fn round(f: f64) -> f64 { + f64::round(f) + } + + #[inline(always)] + pub(crate) fn trunc(f: f64) -> f64 { + f64::trunc(f) + } + + #[inline(always)] + pub(crate) fn ceil(f: f64) -> f64 { + f64::ceil(f) + } + + #[inline(always)] + pub(crate) fn floor(f: f64) -> f64 { + f64::floor(f) + } + + #[inline(always)] + pub(crate) fn exp(f: f64) -> f64 { + f64::exp(f) + } + + #[inline(always)] + pub(crate) fn powf(f: f64, n: f64) -> f64 { + f64::powf(f, n) + } + + #[inline(always)] + pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 { + f64::mul_add(a, b, c) + } + + #[inline] + pub fn div_euclid(a: f64, b: f64) -> f64 { + f64::div_euclid(a, b) + } + + #[inline] + pub fn rem_euclid(a: f64, b: f64) -> f64 { + f64::rem_euclid(a, b) + } +} + +#[cfg(feature = "libm")] +pub(crate) use libm_math::*; + +#[cfg(not(feature = "libm"))] +pub(crate) use std_math::*; |