use core::intrinsics;
use ndless_sys as cmath;
pub trait Float: Sized {
fn floor(self) -> Self;
fn ceil(self) -> Self;
fn round(self) -> Self;
fn trunc(self) -> Self;
fn fract(self) -> Self;
fn abs(self) -> Self;
fn signum(self) -> Self;
#[must_use]
fn copysign(self, y: 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;
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;
#[deprecated(note = "you probably meant `(self - other).abs()`: \
this operation is `(self - other).max(0.0)` (also \
known as `fdim` in C). If you truly need the positive \
difference, consider using that expression or the C function \
`fdim`, depending on how you wish to handle NaN (please consider \
filing an issue describing your use-case too).")]
fn abs_sub(self, other: 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)
where
Self: Sized;
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;
}
impl Float for f64 {
#[inline]
fn floor(self) -> f64 {
unsafe { intrinsics::floorf64(self) }
}
#[inline]
fn ceil(self) -> f64 {
unsafe { intrinsics::ceilf64(self) }
}
#[inline]
fn round(self) -> f64 {
unsafe { intrinsics::roundf64(self) }
}
#[inline]
fn trunc(self) -> f64 {
unsafe { intrinsics::truncf64(self) }
}
#[inline]
fn fract(self) -> f64 {
self - self.trunc()
}
#[inline]
fn abs(self) -> f64 {
unsafe { intrinsics::fabsf64(self) }
}
#[inline]
fn signum(self) -> f64 {
if self.is_nan() {
core::f64::NAN
} else {
unsafe { intrinsics::copysignf64(1.0, self) }
}
}
#[inline]
#[must_use]
fn copysign(self, y: f64) -> f64 {
unsafe { intrinsics::copysignf64(self, y) }
}
#[inline]
fn mul_add(self, a: f64, b: f64) -> f64 {
unsafe { intrinsics::fmaf64(self, a, b) }
}
#[inline]
fn div_euc(self, rhs: f64) -> f64 {
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 powi(self, n: i32) -> f64 {
unsafe { intrinsics::powif64(self, n) }
}
#[inline]
fn powf(self, n: f64) -> f64 {
unsafe { intrinsics::powf64(self, n) }
}
#[inline]
fn sqrt(self) -> f64 {
if self < 0.0 {
core::f64::NAN
} else {
unsafe { intrinsics::sqrtf64(self) }
}
}
#[inline]
fn exp(self) -> f64 {
unsafe { intrinsics::expf64(self) }
}
#[inline]
fn exp2(self) -> f64 {
unsafe { intrinsics::exp2f64(self) }
}
#[inline]
fn ln(self) -> f64 {
unsafe { intrinsics::logf64(self) }
}
#[inline]
fn log(self, base: f64) -> f64 {
self.ln() / base.ln()
}
#[inline]
fn log2(self) -> f64 {
unsafe { intrinsics::log2f64(self) }
}
#[inline]
fn log10(self) -> f64 {
unsafe { intrinsics::log10f64(self) }
}
#[inline]
fn abs_sub(self, other: f64) -> f64 {
unsafe { cmath::fdim(self, other) }
}
#[inline]
fn cbrt(self) -> f64 {
unsafe { cmath::cbrt(self) }
}
#[inline]
fn hypot(self, other: f64) -> f64 {
unsafe { cmath::hypot(self, other) }
}
#[inline]
fn sin(self) -> f64 {
unsafe { intrinsics::sinf64(self) }
}
#[inline]
fn cos(self) -> f64 {
unsafe { intrinsics::cosf64(self) }
}
#[inline]
fn tan(self) -> f64 {
unsafe { cmath::tan(self) }
}
#[inline]
fn asin(self) -> f64 {
unsafe { cmath::asin(self) }
}
#[inline]
fn acos(self) -> f64 {
unsafe { cmath::acos(self) }
}
#[inline]
fn atan(self) -> f64 {
unsafe { cmath::atan(self) }
}
#[inline]
fn atan2(self, other: f64) -> f64 {
unsafe { cmath::atan2(self, other) }
}
#[inline]
fn sin_cos(self) -> (f64, f64) {
(self.sin(), self.cos())
}
#[inline]
fn exp_m1(self) -> f64 {
unsafe { cmath::expm1(self) }
}
#[inline]
fn ln_1p(self) -> f64 {
unsafe { cmath::log1p(self) }
}
#[inline]
fn sinh(self) -> f64 {
unsafe { cmath::sinh(self) }
}
#[inline]
fn cosh(self) -> f64 {
unsafe { cmath::cosh(self) }
}
#[inline]
fn tanh(self) -> f64 {
unsafe { cmath::tanh(self) }
}
#[inline]
fn asinh(self) -> f64 {
if self == core::f64::NEG_INFINITY {
core::f64::NEG_INFINITY
} else {
(self + ((self * self) + 1.0).sqrt()).ln()
}
}
#[inline]
fn acosh(self) -> f64 {
match self {
x if x < 1.0 => core::f64::NAN,
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
#[inline]
fn atanh(self) -> f64 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
}
impl Float for f32 {
#[inline]
fn floor(self) -> f32 {
unsafe { intrinsics::floorf32(self) }
}
#[inline]
fn ceil(self) -> f32 {
unsafe { intrinsics::ceilf32(self) }
}
#[inline]
fn round(self) -> f32 {
unsafe { intrinsics::roundf32(self) }
}
#[inline]
fn trunc(self) -> f32 {
unsafe { intrinsics::truncf32(self) }
}
#[inline]
fn fract(self) -> f32 {
self - self.trunc()
}
#[inline]
fn abs(self) -> f32 {
unsafe { intrinsics::fabsf32(self) }
}
#[inline]
fn signum(self) -> f32 {
if self.is_nan() {
core::f32::NAN
} else {
unsafe { intrinsics::copysignf32(1.0, self) }
}
}
#[inline]
#[must_use]
fn copysign(self, y: f32) -> f32 {
unsafe { intrinsics::copysignf32(self, y) }
}
#[inline]
fn mul_add(self, a: f32, b: f32) -> f32 {
unsafe { intrinsics::fmaf32(self, a, b) }
}
#[inline]
fn div_euc(self, rhs: f32) -> f32 {
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 powi(self, n: i32) -> f32 {
unsafe { intrinsics::powif32(self, n) }
}
#[inline]
fn powf(self, n: f32) -> f32 {
unsafe { intrinsics::powf32(self, n) }
}
#[inline]
fn sqrt(self) -> f32 {
if self < 0.0 {
core::f32::NAN
} else {
unsafe { intrinsics::sqrtf32(self) }
}
}
#[inline]
fn exp(self) -> f32 {
unsafe { intrinsics::expf32(self) }
}
#[inline]
fn exp2(self) -> f32 {
unsafe { intrinsics::exp2f32(self) }
}
#[inline]
fn ln(self) -> f32 {
unsafe { intrinsics::logf32(self) }
}
#[inline]
fn log(self, base: f32) -> f32 {
self.ln() / base.ln()
}
#[inline]
fn log2(self) -> f32 {
unsafe { intrinsics::log2f32(self) }
}
#[inline]
fn log10(self) -> f32 {
unsafe { intrinsics::log10f32(self) }
}
#[inline]
fn abs_sub(self, other: f32) -> f32 {
unsafe { cmath::fdimf(self, other) }
}
#[inline]
fn cbrt(self) -> f32 {
unsafe { cmath::cbrtf(self) }
}
#[inline]
fn hypot(self, other: f32) -> f32 {
unsafe { cmath::hypotf(self, other) }
}
#[inline]
fn sin(self) -> f32 {
unsafe { intrinsics::sinf32(self) }
}
#[inline]
fn cos(self) -> f32 {
unsafe { intrinsics::cosf32(self) }
}
#[inline]
fn tan(self) -> f32 {
unsafe { cmath::tanf(self) }
}
#[inline]
fn asin(self) -> f32 {
unsafe { cmath::asinf(self) }
}
#[inline]
fn acos(self) -> f32 {
unsafe { cmath::acosf(self) }
}
#[inline]
fn atan(self) -> f32 {
unsafe { cmath::atanf(self) }
}
#[inline]
fn atan2(self, other: f32) -> f32 {
unsafe { cmath::atan2f(self, other) }
}
#[inline]
fn sin_cos(self) -> (f32, f32) {
(self.sin(), self.cos())
}
#[inline]
fn exp_m1(self) -> f32 {
unsafe { cmath::expm1f(self) }
}
#[inline]
fn ln_1p(self) -> f32 {
unsafe { cmath::log1pf(self) }
}
#[inline]
fn sinh(self) -> f32 {
unsafe { cmath::sinhf(self) }
}
#[inline]
fn cosh(self) -> f32 {
unsafe { cmath::coshf(self) }
}
#[inline]
fn tanh(self) -> f32 {
unsafe { cmath::tanhf(self) }
}
#[inline]
fn asinh(self) -> f32 {
if self == core::f32::NEG_INFINITY {
core::f32::NEG_INFINITY
} else {
(self + ((self * self) + 1.0).sqrt()).ln()
}
}
#[inline]
fn acosh(self) -> f32 {
match self {
x if x < 1.0 => core::f32::NAN,
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
#[inline]
fn atanh(self) -> f32 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
}