diff options
Diffstat (limited to 'vendor/libm/src/lib.rs')
-rw-r--r-- | vendor/libm/src/lib.rs | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/vendor/libm/src/lib.rs b/vendor/libm/src/lib.rs new file mode 100644 index 000000000..a47883d81 --- /dev/null +++ b/vendor/libm/src/lib.rs @@ -0,0 +1,642 @@ +//! libm in pure Rust +//! +//! # Usage +//! +//! You can use this crate in two ways: +//! +//! - By directly using its free functions, e.g. `libm::powf`. +//! +//! - By importing the `F32Ext` and / or `F64Ext` extension traits to add methods like `powf` to the +//! `f32` and `f64` types. Then you'll be able to invoke math functions as methods, e.g. `x.sqrt()`. + +#![deny(warnings)] +#![no_std] +#![cfg_attr( + all(target_arch = "wasm32", not(feature = "stable")), + feature(core_intrinsics) +)] + +mod math; + +use core::{f32, f64}; + +pub use self::math::*; + +/// Approximate equality with 1 ULP of tolerance +#[doc(hidden)] +#[inline] +pub fn _eqf(a: f32, b: f32) -> Result<(), u32> { + if a.is_nan() && b.is_nan() { + Ok(()) + } else { + let err = (a.to_bits() as i32).wrapping_sub(b.to_bits() as i32).abs(); + + if err <= 1 { + Ok(()) + } else { + Err(err as u32) + } + } +} + +#[doc(hidden)] +#[inline] +pub fn _eq(a: f64, b: f64) -> Result<(), u64> { + if a.is_nan() && b.is_nan() { + Ok(()) + } else { + let err = (a.to_bits() as i64).wrapping_sub(b.to_bits() as i64).abs(); + + if err <= 1 { + Ok(()) + } else { + Err(err as u64) + } + } +} + +/// Math support for `f32` +/// +/// This trait is sealed and cannot be implemented outside of `libm`. +pub trait F32Ext: private::Sealed + Sized { + fn floor(self) -> Self; + + fn ceil(self) -> Self; + + fn round(self) -> Self; + + fn trunc(self) -> Self; + + fn fdim(self, rhs: Self) -> Self; + + fn fract(self) -> Self; + + fn abs(self) -> Self; + + // NOTE depends on unstable intrinsics::copysignf32 + // fn signum(self) -> Self; + + fn mul_add(self, a: Self, b: Self) -> Self; + + fn div_euc(self, rhs: Self) -> Self; + + fn mod_euc(self, rhs: Self) -> Self; + + // NOTE depends on unstable intrinsics::powif32 + // fn powi(self, n: i32) -> Self; + + fn powf(self, n: Self) -> Self; + + fn sqrt(self) -> Self; + + fn exp(self) -> Self; + + fn exp2(self) -> Self; + + fn ln(self) -> Self; + + fn log(self, base: Self) -> Self; + + fn log2(self) -> Self; + + fn log10(self) -> Self; + + fn cbrt(self) -> Self; + + fn hypot(self, other: Self) -> Self; + + fn sin(self) -> Self; + + fn cos(self) -> Self; + + fn tan(self) -> Self; + + fn asin(self) -> Self; + + fn acos(self) -> Self; + + fn atan(self) -> Self; + + fn atan2(self, other: Self) -> Self; + + fn sin_cos(self) -> (Self, Self); + + fn exp_m1(self) -> Self; + + fn ln_1p(self) -> Self; + + fn sinh(self) -> Self; + + fn cosh(self) -> Self; + + fn tanh(self) -> Self; + + fn asinh(self) -> Self; + + fn acosh(self) -> Self; + + fn atanh(self) -> Self; + + fn min(self, other: Self) -> Self; + + fn max(self, other: Self) -> Self; +} + +impl F32Ext for f32 { + #[inline] + fn floor(self) -> Self { + floorf(self) + } + + #[inline] + fn ceil(self) -> Self { + ceilf(self) + } + + #[inline] + fn round(self) -> Self { + roundf(self) + } + + #[inline] + fn trunc(self) -> Self { + truncf(self) + } + + #[inline] + fn fdim(self, rhs: Self) -> Self { + fdimf(self, rhs) + } + + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + #[inline] + fn abs(self) -> Self { + fabsf(self) + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + fmaf(self, a, b) + } + + #[inline] + fn div_euc(self, rhs: Self) -> Self { + let q = (self / rhs).trunc(); + if self % rhs < 0.0 { + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn mod_euc(self, rhs: f32) -> f32 { + let r = self % rhs; + if r < 0.0 { + r + rhs.abs() + } else { + r + } + } + + #[inline] + fn powf(self, n: Self) -> Self { + powf(self, n) + } + + #[inline] + fn sqrt(self) -> Self { + sqrtf(self) + } + + #[inline] + fn exp(self) -> Self { + expf(self) + } + + #[inline] + fn exp2(self) -> Self { + exp2f(self) + } + + #[inline] + fn ln(self) -> Self { + logf(self) + } + + #[inline] + fn log(self, base: Self) -> Self { + self.ln() / base.ln() + } + + #[inline] + fn log2(self) -> Self { + log2f(self) + } + + #[inline] + fn log10(self) -> Self { + log10f(self) + } + + #[inline] + fn cbrt(self) -> Self { + cbrtf(self) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + hypotf(self, other) + } + + #[inline] + fn sin(self) -> Self { + sinf(self) + } + + #[inline] + fn cos(self) -> Self { + cosf(self) + } + + #[inline] + fn tan(self) -> Self { + tanf(self) + } + + #[inline] + fn asin(self) -> Self { + asinf(self) + } + + #[inline] + fn acos(self) -> Self { + acosf(self) + } + + #[inline] + fn atan(self) -> Self { + atanf(self) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + atan2f(self, other) + } + + #[inline] + fn sin_cos(self) -> (Self, Self) { + sincosf(self) + } + + #[inline] + fn exp_m1(self) -> Self { + expm1f(self) + } + + #[inline] + fn ln_1p(self) -> Self { + log1pf(self) + } + + #[inline] + fn sinh(self) -> Self { + sinhf(self) + } + + #[inline] + fn cosh(self) -> Self { + coshf(self) + } + + #[inline] + fn tanh(self) -> Self { + tanhf(self) + } + + #[inline] + fn asinh(self) -> Self { + asinhf(self) + } + + #[inline] + fn acosh(self) -> Self { + acoshf(self) + } + + #[inline] + 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` +/// +/// This trait is sealed and cannot be implemented outside of `libm`. +pub trait F64Ext: private::Sealed + Sized { + fn floor(self) -> Self; + + fn ceil(self) -> Self; + + fn round(self) -> Self; + + fn trunc(self) -> Self; + + fn fdim(self, rhs: Self) -> Self; + + fn fract(self) -> Self; + + fn abs(self) -> Self; + + // NOTE depends on unstable intrinsics::copysignf64 + // fn signum(self) -> Self; + + fn mul_add(self, a: Self, b: Self) -> Self; + + fn div_euc(self, rhs: Self) -> Self; + + fn mod_euc(self, rhs: Self) -> Self; + + // NOTE depends on unstable intrinsics::powif64 + // fn powi(self, n: i32) -> Self; + + fn powf(self, n: Self) -> Self; + + fn sqrt(self) -> Self; + + fn exp(self) -> Self; + + fn exp2(self) -> Self; + + fn ln(self) -> Self; + + fn log(self, base: Self) -> Self; + + fn log2(self) -> Self; + + fn log10(self) -> Self; + + fn cbrt(self) -> Self; + + fn hypot(self, other: Self) -> Self; + + fn sin(self) -> Self; + + fn cos(self) -> Self; + + fn tan(self) -> Self; + + fn asin(self) -> Self; + + fn acos(self) -> Self; + + fn atan(self) -> Self; + + fn atan2(self, other: Self) -> Self; + + fn sin_cos(self) -> (Self, Self); + + fn exp_m1(self) -> Self; + + fn ln_1p(self) -> Self; + + fn sinh(self) -> Self; + + fn cosh(self) -> Self; + + fn tanh(self) -> Self; + + fn asinh(self) -> Self; + + fn acosh(self) -> Self; + + fn atanh(self) -> Self; + + fn min(self, other: Self) -> Self; + + fn max(self, other: Self) -> Self; +} + +impl F64Ext for f64 { + #[inline] + fn floor(self) -> Self { + floor(self) + } + + #[inline] + fn ceil(self) -> Self { + ceil(self) + } + + #[inline] + fn round(self) -> Self { + round(self) + } + + #[inline] + fn trunc(self) -> Self { + trunc(self) + } + + #[inline] + fn fdim(self, rhs: Self) -> Self { + fdim(self, rhs) + } + + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + #[inline] + fn abs(self) -> Self { + fabs(self) + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + fma(self, a, b) + } + + #[inline] + fn div_euc(self, rhs: Self) -> Self { + let q = (self / rhs).trunc(); + if self % rhs < 0.0 { + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn mod_euc(self, rhs: f64) -> f64 { + let r = self % rhs; + if r < 0.0 { + r + rhs.abs() + } else { + r + } + } + + #[inline] + fn powf(self, n: Self) -> Self { + pow(self, n) + } + + #[inline] + fn sqrt(self) -> Self { + sqrt(self) + } + + #[inline] + fn exp(self) -> Self { + exp(self) + } + + #[inline] + fn exp2(self) -> Self { + exp2(self) + } + + #[inline] + fn ln(self) -> Self { + log(self) + } + + #[inline] + fn log(self, base: Self) -> Self { + self.ln() / base.ln() + } + + #[inline] + fn log2(self) -> Self { + log2(self) + } + + #[inline] + fn log10(self) -> Self { + log10(self) + } + + #[inline] + fn cbrt(self) -> Self { + cbrt(self) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + hypot(self, other) + } + + #[inline] + fn sin(self) -> Self { + sin(self) + } + + #[inline] + fn cos(self) -> Self { + cos(self) + } + + #[inline] + fn tan(self) -> Self { + tan(self) + } + + #[inline] + fn asin(self) -> Self { + asin(self) + } + + #[inline] + fn acos(self) -> Self { + acos(self) + } + + #[inline] + fn atan(self) -> Self { + atan(self) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + atan2(self, other) + } + + #[inline] + fn sin_cos(self) -> (Self, Self) { + sincos(self) + } + + #[inline] + fn exp_m1(self) -> Self { + expm1(self) + } + + #[inline] + fn ln_1p(self) -> Self { + log1p(self) + } + + #[inline] + fn sinh(self) -> Self { + sinh(self) + } + + #[inline] + fn cosh(self) -> Self { + cosh(self) + } + + #[inline] + fn tanh(self) -> Self { + tanh(self) + } + + #[inline] + fn asinh(self) -> Self { + asinh(self) + } + + #[inline] + fn acosh(self) -> Self { + acosh(self) + } + + #[inline] + 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 { + pub trait Sealed {} + + impl Sealed for f32 {} + impl Sealed for f64 {} +} + +#[cfg(all(test, feature = "musl-reference-tests"))] +include!(concat!(env!("OUT_DIR"), "/musl-tests.rs")); |