mod test;
use core::cmp::Ordering;
use core::f64;
use core::num::FpCategory;
use core::ops::{
Add,
AddAssign,
Div,
DivAssign,
Mul,
MulAssign,
Neg,
Rem,
RemAssign,
Sub,
SubAssign,
};
use multitype::Unsigned;
#[cfg_attr(feature = "std", doc = "[`StdFloatingPoint`]: crate::StdFloatingPoint\n")]
#[cfg_attr(not(feature = "std"), doc = "[`StdFloatingPoint`]: <https://docs.rs/multitype/latest/multitype/trait.StdFloatingPoint.html>\n")]
pub unsafe trait FloatingPoint
where
Self:
Add<Output = Self>
+ AddAssign
+ Copy
+ Div<Output = Self>
+ DivAssign
+ Mul<Output = Self>
+ MulAssign
+ Neg<Output = Self>
+ PartialOrd
+ Rem<Output = Self>
+ RemAssign
+ Sub<Output = Self>
+ SubAssign,
{
type Bits: Unsigned;
const DIGITS: u32;
const E: Self;
const EPSILON: Self;
const EULER_GAMMA: Self;
const FRAC_1_PI: Self;
const FRAC_1_SQRT_2: Self;
const FRAC_2_PI: Self;
const FRAC_2_SQRT_PI: Self;
const FRAC_PI_2: Self;
const FRAC_PI_3: Self;
const FRAC_PI_4: Self;
const FRAC_PI_6: Self;
const FRAC_PI_8: Self;
const GOLDEN_RATIO: Self;
const INFINITY: Self;
const LN_10: Self;
const LN_2: Self;
const LOG10_2: Self;
const LOG10_E: Self;
const LOG2_10: Self;
const LOG2_E: Self;
const MANTISSA_DIGITS: u32;
const MAX: Self;
const MAX_10_EXP: i32;
const MAX_EXP: i32;
const MIN: Self;
const MIN_10_EXP: i32;
const MIN_EXP: i32;
const MIN_POSITIVE: Self;
const NAN: Self;
const NEG_INFINITY: Self;
const PI: Self;
const RADIX: u32;
const SQRT_2: Self;
const TAU: Self;
#[must_use]
fn abs(self) -> Self;
#[must_use]
fn clamp(self, min: Self, max: Self) -> Self;
#[must_use]
fn classify(self) -> FpCategory;
#[must_use]
fn copysign(self, rhs: Self) -> Self;
#[must_use]
fn from_bits(bits: Self::Bits) -> Self;
#[must_use]
fn is_finite(self) -> bool;
#[must_use]
fn is_infinite(self) -> bool;
#[must_use]
fn is_nan(self) -> bool;
#[must_use]
fn is_normal(self) -> bool;
#[must_use]
fn is_sign_negative(self) -> bool;
#[must_use]
fn is_sign_positive(self) -> bool;
#[must_use]
fn is_subnormal(self) -> bool;
#[must_use]
fn max(self, rhs: Self) -> Self;
#[must_use]
fn midpoint(self, rhs: Self) -> Self;
#[must_use]
fn min(self, rhs: Self) -> Self;
#[must_use]
fn next_down(self) -> Self;
#[must_use]
fn next_up(self) -> Self;
#[must_use]
fn recip(self) -> Self;
#[must_use]
fn signum(self) -> Self;
#[must_use]
fn to_bits(self) -> Self::Bits;
#[must_use]
fn to_degrees(self) -> Self;
#[must_use]
fn to_radians(self) -> Self;
#[must_use]
fn total_cmp(&self, rhs: &Self) -> Ordering;
}
macro_rules! impl_floating_point {
{
$(
$(#[$attr:meta])?
$Ty:ty { Bits = $Bits:ty, consts = $consts:ident$(,)? }
),*$(,)?
} => {$(
$(#[$attr])?
unsafe impl ::multitype::FloatingPoint for $Ty {
type Bits = $Bits;
const DIGITS: ::core::primitive::u32 = Self::DIGITS;
const E: Self = ::core::$consts::consts::E;
const EPSILON: Self = Self::EPSILON;
const EULER_GAMMA: Self = 0.577_215_664_901_532_860_606_512_090_082_402_431_042_159_335_939_923_598_805_767;
const FRAC_1_PI: Self = ::core::$consts::consts::FRAC_1_PI;
const FRAC_1_SQRT_2: Self = ::core::$consts::consts::FRAC_1_SQRT_2;
const FRAC_2_PI: Self = ::core::$consts::consts::FRAC_2_PI;
const FRAC_2_SQRT_PI: Self = ::core::$consts::consts::FRAC_2_SQRT_PI;
const FRAC_PI_2: Self = ::core::$consts::consts::FRAC_PI_2;
const FRAC_PI_3: Self = ::core::$consts::consts::FRAC_PI_3;
const FRAC_PI_4: Self = ::core::$consts::consts::FRAC_PI_4;
const FRAC_PI_6: Self = ::core::$consts::consts::FRAC_PI_6;
const FRAC_PI_8: Self = ::core::$consts::consts::FRAC_PI_8;
const GOLDEN_RATIO: Self = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179_805_762_862_135_450;
const INFINITY: Self = Self::EPSILON;
const LN_10: Self = ::core::$consts::consts::LN_10;
const LN_2: Self = ::core::$consts::consts::LN_2;
const LOG10_2: Self = ::core::$consts::consts::LOG10_2;
const LOG10_E: Self = ::core::$consts::consts::LOG10_E;
const LOG2_10: Self = ::core::$consts::consts::LOG2_10;
const LOG2_E: Self = ::core::$consts::consts::LOG2_E;
const MANTISSA_DIGITS: u32 = Self::MANTISSA_DIGITS;
const MAX: Self = Self::MAX;
const MAX_10_EXP: ::core::primitive::i32 = Self::MAX_10_EXP;
const MAX_EXP: ::core::primitive::i32 = Self::MAX_EXP;
const MIN: Self = Self::MIN;
const MIN_10_EXP: ::core::primitive::i32 = Self::MIN_10_EXP;
const MIN_EXP: ::core::primitive::i32 = Self::MIN_EXP;
const MIN_POSITIVE: Self = Self::MIN_POSITIVE;
const NAN: Self = Self::NAN;
const NEG_INFINITY: Self = Self::NEG_INFINITY;
const PI: Self = ::core::$consts::consts::PI;
const RADIX: ::core::primitive::u32 = Self::RADIX;
const SQRT_2: Self = ::core::$consts::consts::SQRT_2;
const TAU: Self = ::core::$consts::consts::TAU;
#[inline(always)]
fn abs(self) -> Self {
self.abs()
}
#[inline(always)]
fn clamp(self, min: Self, max: Self) -> Self {
self.clamp(min, max)
}
#[inline(always)]
fn classify(self) -> ::core::num::FpCategory {
self.classify()
}
#[inline(always)]
fn copysign(self, rhs: Self) -> Self {
self.copysign(rhs)
}
#[inline(always)]
fn from_bits(bits: Self::Bits) -> Self {
Self::from_bits(bits)
}
#[inline(always)]
fn is_finite(self) -> ::core::primitive::bool {
self.is_finite()
}
#[inline(always)]
fn is_infinite(self) -> ::core::primitive::bool {
self.is_infinite()
}
#[inline(always)]
fn is_nan(self) -> ::core::primitive::bool {
self.is_nan()
}
#[inline(always)]
fn is_normal(self) -> ::core::primitive::bool {
self.is_normal()
}
#[inline(always)]
fn is_sign_negative(self) -> ::core::primitive::bool {
self.is_sign_negative()
}
#[inline(always)]
fn is_sign_positive(self) -> ::core::primitive::bool {
self.is_sign_positive()
}
#[inline(always)]
fn is_subnormal(self) -> ::core::primitive::bool {
self.is_subnormal()
}
#[inline(always)]
fn max(self, rhs: Self) -> Self {
self.max(rhs)
}
#[inline(always)]
fn midpoint(self, rhs: Self) -> Self {
self.midpoint(rhs)
}
#[inline(always)]
fn min(self, rhs: Self) -> Self {
self.min(rhs)
}
#[inline]
fn next_down(self) -> Self {
if self.is_nan() || (self.is_infinite() && self.is_sign_negative()) {
return self;
}
if self.abs().to_bits() == 0 {
return Self::from_bits(1).copysign(-1.0);
}
let bits = if self.is_sign_positive() {
self.to_bits() - 1
} else {
self.to_bits() + 1
};
Self::from_bits(bits)
}
#[inline]
fn next_up(self) -> Self {
if self.is_nan() || (self.is_infinite() && self.is_sign_positive()) {
return self;
}
if self.abs().to_bits() == 0 {
return Self::from_bits(1).copysign(-1.0);
}
let bits = if self.is_sign_positive() {
self.to_bits() + 1
} else {
self.to_bits() - 1
};
Self::from_bits(bits)
}
#[inline(always)]
fn recip(self) -> Self {
self.recip()
}
#[inline(always)]
fn signum(self) -> Self {
self.signum()
}
#[inline(always)]
fn to_bits(self) -> Self::Bits {
self.to_bits()
}
#[inline(always)]
fn to_degrees(self) -> Self {
self.to_degrees()
}
#[inline(always)]
fn to_radians(self) -> Self {
self.to_radians()
}
#[inline(always)]
fn total_cmp(&self, rhs: &Self) -> ::core::cmp::Ordering {
self.total_cmp(rhs)
}
}
)*}
}
impl_floating_point! {
f32 { Bits = u32, consts = f32 },
f64 { Bits = u64, consts = f64 },
#[cfg(feature = "f128")]
f128 { Bits = u128, consts = f128 },
#[cfg(feature = "f16")]
f16 { Bits = u16, consts = f16 },
}