summaryrefslogtreecommitdiffstats
path: root/vendor/libm/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/libm/src/lib.rs')
-rw-r--r--vendor/libm/src/lib.rs642
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"));