#![no_std]
#![warn(missing_docs)]
pub trait CoreFloat: Sized + Copy {
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;
fn copysign(self, sign: Self) -> Self;
fn mul_add(self, a: Self, b: Self) -> Self;
fn div_euclid(self, rhs: Self) -> Self;
fn rem_euclid(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;
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) {
(self.sin(), self.cos())
}
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 CoreFloat for f32 {
#[inline]
fn floor(self) -> Self {
libm::floorf(self)
}
#[inline]
fn ceil(self) -> Self {
libm::ceilf(self)
}
#[inline]
fn round(self) -> Self {
libm::roundf(self)
}
#[inline]
fn trunc(self) -> Self {
libm::truncf(self)
}
#[inline]
fn fract(self) -> Self {
self - self.trunc()
}
#[inline]
fn abs(self) -> Self {
libm::fabsf(self)
}
#[inline]
fn signum(self) -> Self {
if self.is_nan() {
Self::NAN
} else {
1.0_f32.copysign(self)
}
}
#[inline]
fn copysign(self, sign: Self) -> Self {
libm::copysignf(self, sign)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
libm::fmaf(self, a, b)
}
#[inline]
fn div_euclid(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 rem_euclid(self, rhs: Self) -> Self {
let r = self % rhs;
if r < 0.0 {
r + rhs.abs()
} else {
r
}
}
#[inline]
fn powi(self, exp: i32) -> Self {
if exp == 0 {
return 1.0;
}
let mut base = if exp < 0 { self.recip() } else { self };
let mut exp = exp.unsigned_abs();
let mut acc = 1.0;
while exp > 1 {
if (exp & 1) == 1 {
acc *= base;
}
exp /= 2;
base = base * base;
}
acc * base
}
#[inline]
fn powf(self, n: Self) -> Self {
libm::powf(self, n)
}
#[inline]
fn sqrt(self) -> Self {
libm::sqrtf(self)
}
#[inline]
fn exp(self) -> Self {
libm::expf(self)
}
#[inline]
fn exp2(self) -> Self {
libm::exp2f(self)
}
#[inline]
fn ln(self) -> Self {
libm::logf(self)
}
#[inline]
fn log(self, base: Self) -> Self {
self.ln() / base.ln()
}
#[inline]
fn log2(self) -> Self {
libm::log2f(self)
}
#[inline]
fn log10(self) -> Self {
libm::log10f(self)
}
#[inline]
fn cbrt(self) -> Self {
libm::cbrtf(self)
}
#[inline]
fn hypot(self, other: Self) -> Self {
libm::hypotf(self, other)
}
#[inline]
fn sin(self) -> Self {
libm::sinf(self)
}
#[inline]
fn cos(self) -> Self {
libm::cosf(self)
}
#[inline]
fn tan(self) -> Self {
libm::tanf(self)
}
#[inline]
fn asin(self) -> Self {
libm::asinf(self)
}
#[inline]
fn acos(self) -> Self {
libm::acosf(self)
}
#[inline]
fn atan(self) -> Self {
libm::atanf(self)
}
#[inline]
fn atan2(self, other: Self) -> Self {
libm::atan2f(self, other)
}
#[inline]
fn exp_m1(self) -> Self {
libm::expm1f(self)
}
#[inline]
fn ln_1p(self) -> Self {
libm::log1pf(self)
}
#[inline]
fn sinh(self) -> Self {
libm::sinhf(self)
}
#[inline]
fn cosh(self) -> Self {
libm::coshf(self)
}
#[inline]
fn tanh(self) -> Self {
libm::tanhf(self)
}
#[inline]
fn asinh(self) -> Self {
let ax = self.abs();
let ix = 1.0 / ax;
(ax + (ax / (Self::hypot(1.0, ix) + ix)))
.ln_1p()
.copysign(self)
}
#[inline]
fn acosh(self) -> Self {
if self < 1.0 {
Self::NAN
} else {
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
}
}
#[inline]
fn atanh(self) -> Self {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
}
impl CoreFloat for f64 {
#[inline]
fn floor(self) -> Self {
libm::floor(self)
}
#[inline]
fn ceil(self) -> Self {
libm::ceil(self)
}
#[inline]
fn round(self) -> Self {
libm::round(self)
}
#[inline]
fn trunc(self) -> Self {
libm::trunc(self)
}
#[inline]
fn fract(self) -> Self {
self - self.trunc()
}
#[inline]
fn abs(self) -> Self {
libm::fabs(self)
}
#[inline]
fn signum(self) -> Self {
if self.is_nan() {
Self::NAN
} else {
1.0_f64.copysign(self)
}
}
#[inline]
fn copysign(self, sign: Self) -> Self {
libm::copysign(self, sign)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
libm::fma(self, a, b)
}
#[inline]
fn div_euclid(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 rem_euclid(self, rhs: Self) -> Self {
let r = self % rhs;
if r < 0.0 {
r + rhs.abs()
} else {
r
}
}
#[inline]
fn powi(self, exp: i32) -> Self {
if exp == 0 {
return 1.0;
}
let mut base = if exp < 0 { self.recip() } else { self };
let mut exp = exp.unsigned_abs();
let mut acc = 1.0;
while exp > 1 {
if (exp & 1) == 1 {
acc *= base;
}
exp /= 2;
base = base * base;
}
acc * base
}
#[inline]
fn powf(self, n: Self) -> Self {
libm::pow(self, n)
}
#[inline]
fn sqrt(self) -> Self {
libm::sqrt(self)
}
#[inline]
fn exp(self) -> Self {
libm::exp(self)
}
#[inline]
fn exp2(self) -> Self {
libm::exp2(self)
}
#[inline]
fn ln(self) -> Self {
libm::log(self)
}
#[inline]
fn log(self, base: Self) -> Self {
self.ln() / base.ln()
}
#[inline]
fn log2(self) -> Self {
libm::log2(self)
}
#[inline]
fn log10(self) -> Self {
libm::log10(self)
}
#[inline]
fn cbrt(self) -> Self {
libm::cbrt(self)
}
#[inline]
fn hypot(self, other: Self) -> Self {
libm::hypot(self, other)
}
#[inline]
fn sin(self) -> Self {
libm::sin(self)
}
#[inline]
fn cos(self) -> Self {
libm::cos(self)
}
#[inline]
fn tan(self) -> Self {
libm::tan(self)
}
#[inline]
fn asin(self) -> Self {
libm::asin(self)
}
#[inline]
fn acos(self) -> Self {
libm::acos(self)
}
#[inline]
fn atan(self) -> Self {
libm::atan(self)
}
#[inline]
fn atan2(self, other: Self) -> Self {
libm::atan2(self, other)
}
#[inline]
fn exp_m1(self) -> Self {
libm::expm1(self)
}
#[inline]
fn ln_1p(self) -> Self {
libm::log1p(self)
}
#[inline]
fn sinh(self) -> Self {
libm::sinh(self)
}
#[inline]
fn cosh(self) -> Self {
libm::cosh(self)
}
#[inline]
fn tanh(self) -> Self {
libm::tanh(self)
}
#[inline]
fn asinh(self) -> Self {
let ax = self.abs();
let ix = 1.0 / ax;
(ax + (ax / (Self::hypot(1.0, ix) + ix)))
.ln_1p()
.copysign(self)
}
#[inline]
fn acosh(self) -> Self {
if self < 1.0 {
Self::NAN
} else {
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
}
}
#[inline]
fn atanh(self) -> Self {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
}