use crate::comparison::traits::{Max, Min};
use crate::named::Named;
use crate::num::arithmetic::traits::{
Abs, AbsAssign, AddMul, AddMulAssign, Ceiling, CeilingAssign, CeilingLogBase2,
CeilingLogBasePowerOf2, CheckedLogBase2, CheckedLogBasePowerOf2, Floor, FloorAssign,
FloorLogBase2, FloorLogBasePowerOf2, IsPowerOf2, Ln, NegAssign, NextPowerOf2,
NextPowerOf2Assign, Pow, PowAssign, PowerOf2, Reciprocal, ReciprocalAssign, Sign, Sqrt,
SqrtAssign, Square, SquareAssign, SubMul, SubMulAssign,
};
use crate::num::basic::traits::{
GaussConstant, Infinity, LemniscateConstant, Ln2, Log2E, NaN, NegativeInfinity, NegativeOne,
NegativeZero, One, OneHalf, OneOverPi, OneOverSqrtPi, OneOverSqrtTau, Phi, Pi, PiOver2,
PiOver3, PiOver4, PiOver6, PiOver8, PrimeConstant, ProuhetThueMorseConstant, Sqrt2, Sqrt2Over2,
Sqrt3, Sqrt3Over3, SqrtPi, Tau, Two, TwoOverPi, TwoOverSqrtPi, Zero,
};
use crate::num::comparison::traits::{EqAbs, PartialOrdAbs};
use crate::num::conversion::traits::{
ConvertibleFrom, ExactInto, IntegerMantissaAndExponent, IsInteger, RawMantissaAndExponent,
RoundingFrom, RoundingInto, SciMantissaAndExponent, WrappingFrom,
};
use crate::num::float::FmtRyuString;
use crate::num::logic::traits::{BitAccess, LowMask, SignificantBits, TrailingZeros};
use core::cmp::Ordering::*;
use core::fmt::{Debug, Display, LowerExp, UpperExp};
use core::iter::{Product, Sum};
use core::num::FpCategory;
use core::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};
use core::panic::RefUnwindSafe;
use core::str::FromStr;
pub trait PrimitiveFloat:
'static
+ Abs<Output = Self>
+ AbsAssign
+ Add<Output = Self>
+ AddAssign<Self>
+ AddMul<Output = Self>
+ AddMulAssign<Self, Self>
+ Ceiling<Output = Self>
+ CeilingAssign
+ CeilingLogBase2<Output = i64>
+ CeilingLogBasePowerOf2<u64, Output = i64>
+ CheckedLogBase2<Output = i64>
+ CheckedLogBasePowerOf2<u64, Output = i64>
+ ConvertibleFrom<u8>
+ ConvertibleFrom<u16>
+ ConvertibleFrom<u32>
+ ConvertibleFrom<u64>
+ ConvertibleFrom<u128>
+ ConvertibleFrom<usize>
+ ConvertibleFrom<i8>
+ ConvertibleFrom<i16>
+ ConvertibleFrom<i32>
+ ConvertibleFrom<i64>
+ ConvertibleFrom<i128>
+ ConvertibleFrom<isize>
+ Copy
+ Debug
+ Default
+ Display
+ Div<Output = Self>
+ DivAssign
+ EqAbs<Self>
+ Floor<Output = Self>
+ FloorAssign
+ FloorLogBase2<Output = i64>
+ FloorLogBasePowerOf2<u64, Output = i64>
+ FmtRyuString
+ From<f32>
+ FromStr
+ Infinity
+ IntegerMantissaAndExponent<u64, i64>
+ Into<f64>
+ IsInteger
+ IsPowerOf2
+ Log2E
+ Ln
+ Ln2
+ LowerExp
+ Min
+ Max
+ Mul<Output = Self>
+ MulAssign<Self>
+ Named
+ NaN
+ NegativeInfinity
+ NegativeZero
+ Neg<Output = Self>
+ NegAssign
+ NegativeOne
+ NextPowerOf2<Output = Self>
+ NextPowerOf2Assign
+ One
+ PartialEq<Self>
+ PartialOrd<Self>
+ PartialOrdAbs<Self>
+ Phi
+ Pi
+ Pow<i64, Output = Self>
+ Pow<Self, Output = Self>
+ PowAssign<i64>
+ PowAssign<Self>
+ PowerOf2<i64>
+ PowerOf2<u64>
+ PrimeConstant
+ Product
+ RawMantissaAndExponent<u64, u64>
+ Reciprocal<Output = Self>
+ ReciprocalAssign
+ RefUnwindSafe
+ Rem<Output = Self>
+ RemAssign<Self>
+ RoundingFrom<u8>
+ RoundingFrom<u16>
+ RoundingFrom<u32>
+ RoundingFrom<u64>
+ RoundingFrom<u128>
+ RoundingFrom<usize>
+ RoundingFrom<i8>
+ RoundingFrom<i16>
+ RoundingFrom<i32>
+ RoundingFrom<i64>
+ RoundingFrom<i128>
+ RoundingFrom<isize>
+ RoundingInto<u8>
+ RoundingInto<u16>
+ RoundingInto<u32>
+ RoundingInto<u64>
+ RoundingInto<u128>
+ RoundingInto<usize>
+ RoundingInto<i8>
+ RoundingInto<i16>
+ RoundingInto<i32>
+ RoundingInto<i64>
+ RoundingInto<i128>
+ RoundingInto<isize>
+ SciMantissaAndExponent<Self, i64>
+ Sign
+ Sized
+ Sqrt<Output = Self>
+ SqrtAssign
+ Sqrt2
+ Sqrt2Over2
+ Sqrt3
+ Sqrt3Over3
+ Square<Output = Self>
+ SquareAssign
+ Sub<Output = Self>
+ SubAssign<Self>
+ SubMul<Output = Self>
+ SubMulAssign<Self, Self>
+ Sum<Self>
+ ProuhetThueMorseConstant
+ Two
+ UpperExp
+ Zero
{
const WIDTH: u64;
const EXPONENT_WIDTH: u64 = Self::WIDTH - Self::MANTISSA_WIDTH - 1;
const MANTISSA_WIDTH: u64;
const MIN_NORMAL_EXPONENT: i64 = -(1 << (Self::EXPONENT_WIDTH - 1)) + 2;
const MIN_EXPONENT: i64 = Self::MIN_NORMAL_EXPONENT - (Self::MANTISSA_WIDTH as i64);
const MAX_EXPONENT: i64 = (1 << (Self::EXPONENT_WIDTH - 1)) - 1;
const MIN_POSITIVE_SUBNORMAL: Self;
const MAX_SUBNORMAL: Self;
const MIN_POSITIVE_NORMAL: Self;
const MAX_FINITE: Self;
const SMALLEST_UNREPRESENTABLE_UINT: u64;
const LARGEST_ORDERED_REPRESENTATION: u64;
fn is_nan(self) -> bool;
fn is_infinite(self) -> bool;
fn is_finite(self) -> bool;
fn is_normal(self) -> bool;
fn is_sign_positive(self) -> bool;
fn is_sign_negative(self) -> bool;
fn classify(self) -> FpCategory;
fn to_bits(self) -> u64;
fn from_bits(v: u64) -> Self;
#[inline]
fn is_negative_zero(self) -> bool {
self.sign() == Less && self == Self::ZERO
}
#[inline]
fn abs_negative_zero(self) -> Self {
if self == Self::ZERO { Self::ZERO } else { self }
}
#[inline]
fn abs_negative_zero_assign(&mut self) {
if *self == Self::ZERO {
*self = Self::ZERO;
}
}
fn next_higher(self) -> Self {
assert!(!self.is_nan());
if self.sign() == Greater {
assert_ne!(self, Self::INFINITY);
Self::from_bits(self.to_bits() + 1)
} else if self == Self::ZERO {
Self::ZERO
} else {
Self::from_bits(self.to_bits() - 1)
}
}
fn next_lower(self) -> Self {
assert!(!self.is_nan());
if self.sign() == Less {
assert_ne!(self, Self::NEGATIVE_INFINITY);
Self::from_bits(self.to_bits() + 1)
} else if self == Self::ZERO {
Self::NEGATIVE_ZERO
} else {
Self::from_bits(self.to_bits() - 1)
}
}
fn to_ordered_representation(self) -> u64 {
assert!(!self.is_nan());
let bits = self.to_bits();
if self.sign() == Greater {
(u64::low_mask(Self::EXPONENT_WIDTH) << Self::MANTISSA_WIDTH) + bits + 1
} else {
(u64::low_mask(Self::EXPONENT_WIDTH + 1) << Self::MANTISSA_WIDTH) - bits
}
}
fn from_ordered_representation(n: u64) -> Self {
let zero_exp = u64::low_mask(Self::EXPONENT_WIDTH) << Self::MANTISSA_WIDTH;
let f = if n <= zero_exp {
Self::from_bits((u64::low_mask(Self::EXPONENT_WIDTH + 1) << Self::MANTISSA_WIDTH) - n)
} else {
let f = Self::from_bits(n - zero_exp - 1);
assert_eq!(f.sign(), Greater);
f
};
assert!(!f.is_nan());
f
}
fn precision(self) -> u64 {
assert!(self.is_finite());
assert!(self != Self::ZERO);
let (mut mantissa, exponent) = self.raw_mantissa_and_exponent();
if exponent == 0 {
mantissa.significant_bits() - TrailingZeros::trailing_zeros(mantissa)
} else {
mantissa.set_bit(Self::MANTISSA_WIDTH);
Self::MANTISSA_WIDTH + 1 - TrailingZeros::trailing_zeros(mantissa)
}
}
fn max_precision_for_sci_exponent(exponent: i64) -> u64 {
assert!(exponent >= Self::MIN_EXPONENT);
assert!(exponent <= Self::MAX_EXPONENT);
if exponent >= Self::MIN_NORMAL_EXPONENT {
Self::MANTISSA_WIDTH + 1
} else {
u64::wrapping_from(exponent - Self::MIN_EXPONENT) + 1
}
}
}
macro_rules! impl_basic_traits_primitive_float {
(
$t: ident,
$width: expr,
$min_positive_subnormal: expr,
$max_subnormal: expr,
$min_positive_normal: expr,
$prouhet_thue_morse_constant: expr,
$prime_constant: expr,
$sqrt_3: expr,
$sqrt_3_over_3: expr,
$phi: expr,
$sqrt_pi: expr,
$one_over_sqrt_pi: expr,
$one_over_sqrt_tau: expr,
$gauss_constant: expr,
$lemniscate_constant: expr
) => {
impl PrimitiveFloat for $t {
const WIDTH: u64 = $width;
const MANTISSA_WIDTH: u64 = ($t::MANTISSA_DIGITS as u64) - 1;
const MAX_FINITE: Self = $t::MAX;
const MIN_POSITIVE_SUBNORMAL: Self = $min_positive_subnormal;
const MAX_SUBNORMAL: Self = $max_subnormal;
const MIN_POSITIVE_NORMAL: Self = $min_positive_normal;
const SMALLEST_UNREPRESENTABLE_UINT: u64 = (1 << (Self::MANTISSA_WIDTH + 1)) + 1;
const LARGEST_ORDERED_REPRESENTATION: u64 = (1u64 << ($width - 1) << 1)
.wrapping_sub(((1 << Self::MANTISSA_WIDTH) - 1) << 1)
- 1;
#[inline]
fn is_nan(self) -> bool {
$t::is_nan(self)
}
#[inline]
fn is_infinite(self) -> bool {
$t::is_infinite(self)
}
#[inline]
fn is_finite(self) -> bool {
$t::is_finite(self)
}
#[inline]
fn is_normal(self) -> bool {
$t::is_normal(self)
}
#[inline]
fn is_sign_positive(self) -> bool {
$t::is_sign_positive(self)
}
#[inline]
fn is_sign_negative(self) -> bool {
$t::is_sign_negative(self)
}
#[inline]
fn classify(self) -> FpCategory {
$t::classify(self)
}
#[inline]
fn to_bits(self) -> u64 {
u64::wrapping_from($t::to_bits(self))
}
#[inline]
fn from_bits(v: u64) -> $t {
$t::from_bits(v.exact_into())
}
}
impl_named!($t);
impl Zero for $t {
const ZERO: $t = 0.0;
}
impl One for $t {
const ONE: $t = 1.0;
}
impl Two for $t {
const TWO: $t = 2.0;
}
impl OneHalf for $t {
const ONE_HALF: $t = 0.5;
}
impl NegativeOne for $t {
const NEGATIVE_ONE: $t = -1.0;
}
impl NegativeZero for $t {
const NEGATIVE_ZERO: $t = -0.0;
}
impl Infinity for $t {
const INFINITY: $t = $t::INFINITY;
}
impl NegativeInfinity for $t {
const NEGATIVE_INFINITY: $t = $t::NEG_INFINITY;
}
impl NaN for $t {
const NAN: $t = $t::NAN;
}
impl Min for $t {
const MIN: $t = $t::NEGATIVE_INFINITY;
}
impl Max for $t {
const MAX: $t = $t::INFINITY;
}
impl ProuhetThueMorseConstant for $t {
const PROUHET_THUE_MORSE_CONSTANT: $t = $prouhet_thue_morse_constant;
}
impl PrimeConstant for $t {
const PRIME_CONSTANT: $t = $prime_constant;
}
impl Ln2 for $t {
const LN_2: $t = core::$t::consts::LN_2;
}
impl Log2E for $t {
const LOG_2_E: $t = core::$t::consts::LOG2_E;
}
impl Sqrt2 for $t {
const SQRT_2: $t = core::$t::consts::SQRT_2;
}
impl Sqrt3 for $t {
const SQRT_3: $t = $sqrt_3;
}
impl Sqrt2Over2 for $t {
const SQRT_2_OVER_2: $t = core::$t::consts::FRAC_1_SQRT_2;
}
impl Sqrt3Over3 for $t {
const SQRT_3_OVER_3: $t = $sqrt_3_over_3;
}
impl Phi for $t {
const PHI: $t = $phi;
}
impl Pi for $t {
const PI: $t = core::$t::consts::PI;
}
impl Tau for $t {
const TAU: $t = core::$t::consts::TAU;
}
impl PiOver2 for $t {
const PI_OVER_2: $t = core::$t::consts::FRAC_PI_2;
}
impl PiOver3 for $t {
const PI_OVER_3: $t = core::$t::consts::FRAC_PI_3;
}
impl PiOver4 for $t {
const PI_OVER_4: $t = core::$t::consts::FRAC_PI_4;
}
impl PiOver6 for $t {
const PI_OVER_6: $t = core::$t::consts::FRAC_PI_6;
}
impl PiOver8 for $t {
const PI_OVER_8: $t = core::$t::consts::FRAC_PI_8;
}
impl OneOverPi for $t {
const ONE_OVER_PI: $t = core::$t::consts::FRAC_1_PI;
}
impl SqrtPi for $t {
const SQRT_PI: $t = $sqrt_pi;
}
impl OneOverSqrtPi for $t {
const ONE_OVER_SQRT_PI: $t = $one_over_sqrt_pi;
}
impl OneOverSqrtTau for $t {
const ONE_OVER_SQRT_TAU: $t = $one_over_sqrt_tau;
}
impl TwoOverPi for $t {
const TWO_OVER_PI: $t = core::$t::consts::FRAC_2_PI;
}
impl TwoOverSqrtPi for $t {
const TWO_OVER_SQRT_PI: $t = core::$t::consts::FRAC_2_SQRT_PI;
}
impl GaussConstant for $t {
const GAUSS_CONSTANT: $t = $gauss_constant;
}
impl LemniscateConstant for $t {
const LEMNISCATE_CONSTANT: $t = $lemniscate_constant;
}
};
}
impl_basic_traits_primitive_float!(
f32,
32,
1.0e-45,
1.1754942e-38,
1.1754944e-38,
0.41245404,
0.4146825,
1.7320508,
0.57735026,
1.618034,
1.7724539,
0.5641896,
0.3989423,
0.83462685,
2.6220574
);
impl_basic_traits_primitive_float!(
f64,
64,
5.0e-324,
2.225073858507201e-308,
2.2250738585072014e-308,
0.4124540336401076,
0.41468250985111166,
1.7320508075688772,
0.5773502691896257,
1.618033988749895,
1.772453850905516,
0.5641895835477563,
0.3989422804014327,
0.8346268416740732,
2.6220575542921196
);