use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub trait Numeric:
Copy
+ Clone
+ PartialEq
+ PartialOrd
+ core::fmt::Debug
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Neg<Output = Self>
+ AddAssign
+ SubAssign
+ MulAssign
+ DivAssign
{
const ZERO: Self;
const ONE: Self;
const TWO: Self;
const HALF: Self;
const PI: Self;
const EPSILON: Self;
const NAN: Self;
const INFINITY: Self;
const NEG_INFINITY: Self;
const MAX: Self;
const MIN_POSITIVE: Self;
fn from_f64(value: f64) -> Self;
fn from_u64(value: u64) -> Self;
fn from_usize(value: usize) -> Self;
fn abs(self) -> Self;
fn sqrt(self) -> Self;
fn sin(self) -> Self;
fn cos(self) -> Self;
fn tan(self) -> Self;
fn exp(self) -> Self;
fn ln(self) -> Self;
#[inline]
fn powi(self, n: i32) -> Self {
let mut exponent = n.unsigned_abs();
let mut base = self;
let mut acc = Self::ONE;
while exponent > 0 {
if exponent & 1 == 1 {
acc *= base;
}
exponent >>= 1;
if exponent > 0 {
base *= base;
}
}
if n < 0 { Self::ONE / acc } else { acc }
}
fn is_nan(self) -> bool;
fn is_finite(self) -> bool;
}
impl Numeric for f64 {
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
const TWO: Self = 2.0;
const HALF: Self = 0.5;
const PI: Self = core::f64::consts::PI;
const EPSILON: Self = f64::EPSILON;
const NAN: Self = f64::NAN;
const INFINITY: Self = f64::INFINITY;
const NEG_INFINITY: Self = f64::NEG_INFINITY;
const MAX: Self = f64::MAX;
const MIN_POSITIVE: Self = f64::MIN_POSITIVE;
#[inline]
fn from_f64(value: f64) -> Self {
value
}
#[inline]
fn from_u64(value: u64) -> Self {
value as f64
}
#[inline]
fn from_usize(value: usize) -> Self {
value as f64
}
#[inline]
fn abs(self) -> Self {
libm::fabs(self)
}
#[inline]
fn sqrt(self) -> Self {
libm::sqrt(self)
}
#[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 exp(self) -> Self {
libm::exp(self)
}
#[inline]
fn ln(self) -> Self {
libm::log(self)
}
#[inline]
fn is_nan(self) -> bool {
f64::is_nan(self)
}
#[inline]
fn is_finite(self) -> bool {
f64::is_finite(self)
}
}
impl Numeric for f32 {
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
const TWO: Self = 2.0;
const HALF: Self = 0.5;
const PI: Self = core::f32::consts::PI;
const EPSILON: Self = f32::EPSILON;
const NAN: Self = f32::NAN;
const INFINITY: Self = f32::INFINITY;
const NEG_INFINITY: Self = f32::NEG_INFINITY;
const MAX: Self = f32::MAX;
const MIN_POSITIVE: Self = f32::MIN_POSITIVE;
#[inline]
fn from_f64(value: f64) -> Self {
value as f32
}
#[inline]
fn from_u64(value: u64) -> Self {
value as f32
}
#[inline]
fn from_usize(value: usize) -> Self {
value as f32
}
#[inline]
fn abs(self) -> Self {
libm::fabsf(self)
}
#[inline]
fn sqrt(self) -> Self {
libm::sqrtf(self)
}
#[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 exp(self) -> Self {
libm::expf(self)
}
#[inline]
fn ln(self) -> Self {
libm::logf(self)
}
#[inline]
fn is_nan(self) -> bool {
f32::is_nan(self)
}
#[inline]
fn is_finite(self) -> bool {
f32::is_finite(self)
}
}