use crate::{PrimitiveNumber, PrimitiveNumberRef, PrimitiveUnsigned};
use core::cmp::Ordering;
use core::f32::consts as f32_consts;
use core::f64::consts as f64_consts;
use core::num::{FpCategory, ParseFloatError};
struct SealedToken;
#[cfg_attr(feature = "std", doc = "```")]
#[cfg_attr(not(feature = "std"), doc = "```ignore")]
pub trait PrimitiveFloat:
PrimitiveNumber
+ PrimitiveFloatToInt<i8>
+ PrimitiveFloatToInt<i16>
+ PrimitiveFloatToInt<i32>
+ PrimitiveFloatToInt<i64>
+ PrimitiveFloatToInt<i128>
+ PrimitiveFloatToInt<isize>
+ PrimitiveFloatToInt<u8>
+ PrimitiveFloatToInt<u16>
+ PrimitiveFloatToInt<u32>
+ PrimitiveFloatToInt<u64>
+ PrimitiveFloatToInt<u128>
+ PrimitiveFloatToInt<usize>
+ core::convert::From<i8>
+ core::convert::From<u8>
+ core::ops::Neg<Output = Self>
+ core::str::FromStr<Err = ParseFloatError>
{
const DIGITS: u32;
const EPSILON: Self;
const INFINITY: 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 RADIX: u32;
const E: 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 LN_2: Self;
const LN_10: Self;
const LOG2_10: Self;
const LOG2_E: Self;
const LOG10_2: Self;
const LOG10_E: Self;
const PI: Self;
const SQRT_2: Self;
const TAU: Self;
type Bits: PrimitiveUnsigned;
fn abs(self) -> Self;
fn clamp(self, min: Self, max: Self) -> Self;
fn classify(self) -> FpCategory;
fn copysign(self, sign: Self) -> Self;
fn from_bits(value: Self::Bits) -> Self;
fn is_finite(self) -> bool;
fn is_infinite(self) -> bool;
fn is_nan(self) -> bool;
fn is_normal(self) -> bool;
fn is_sign_negative(self) -> bool;
fn is_sign_positive(self) -> bool;
fn is_subnormal(self) -> bool;
fn max(self, other: Self) -> Self;
fn min(self, other: Self) -> Self;
fn next_down(self) -> Self;
fn next_up(self) -> Self;
fn recip(self) -> Self;
fn signum(self) -> Self;
fn to_bits(self) -> Self::Bits;
fn to_degrees(self) -> Self;
fn to_radians(self) -> Self;
fn total_cmp(&self, other: &Self) -> Ordering;
unsafe fn to_int_unchecked<Int>(self) -> Int
where
Self: PrimitiveFloatToInt<Int>;
#[cfg(feature = "std")]
fn acos(self) -> Self;
#[cfg(feature = "std")]
fn acosh(self) -> Self;
#[cfg(feature = "std")]
fn asin(self) -> Self;
#[cfg(feature = "std")]
fn asinh(self) -> Self;
#[cfg(feature = "std")]
fn atan(self) -> Self;
#[cfg(feature = "std")]
fn atan2(self, other: Self) -> Self;
#[cfg(feature = "std")]
fn atanh(self) -> Self;
#[cfg(feature = "std")]
fn cbrt(self) -> Self;
#[cfg(feature = "std")]
fn ceil(self) -> Self;
#[cfg(feature = "std")]
fn cos(self) -> Self;
#[cfg(feature = "std")]
fn cosh(self) -> Self;
#[cfg(feature = "std")]
fn div_euclid(self, rhs: Self) -> Self;
#[cfg(feature = "std")]
fn exp(self) -> Self;
#[cfg(feature = "std")]
fn exp2(self) -> Self;
#[cfg(feature = "std")]
fn exp_m1(self) -> Self;
#[cfg(feature = "std")]
fn floor(self) -> Self;
#[cfg(feature = "std")]
fn fract(self) -> Self;
#[cfg(feature = "std")]
fn hypot(self, other: Self) -> Self;
#[cfg(feature = "std")]
fn ln(self) -> Self;
#[cfg(feature = "std")]
fn ln_1p(self) -> Self;
#[cfg(feature = "std")]
fn log(self, base: Self) -> Self;
#[cfg(feature = "std")]
fn log2(self) -> Self;
#[cfg(feature = "std")]
fn log10(self) -> Self;
#[cfg(feature = "std")]
fn mul_add(self, a: Self, b: Self) -> Self;
#[cfg(feature = "std")]
fn powf(self, n: Self) -> Self;
#[cfg(feature = "std")]
fn powi(self, n: i32) -> Self;
#[cfg(feature = "std")]
fn rem_euclid(self, rhs: Self) -> Self;
#[cfg(feature = "std")]
fn round(self) -> Self;
#[cfg(feature = "std")]
fn round_ties_even(self) -> Self;
#[cfg(feature = "std")]
fn sin(self) -> Self;
#[cfg(feature = "std")]
fn sin_cos(self) -> (Self, Self);
#[cfg(feature = "std")]
fn sinh(self) -> Self;
#[cfg(feature = "std")]
fn sqrt(self) -> Self;
#[cfg(feature = "std")]
fn tan(self) -> Self;
#[cfg(feature = "std")]
fn tanh(self) -> Self;
#[cfg(feature = "std")]
fn trunc(self) -> Self;
}
pub trait PrimitiveFloatRef<T>: PrimitiveNumberRef<T> + core::ops::Neg<Output = T> {}
pub trait PrimitiveFloatToInt<Int> {
#[doc(hidden)]
#[expect(private_interfaces)]
unsafe fn __to_int_unchecked(x: Self, _: SealedToken) -> Int;
}
macro_rules! impl_float {
($Float:ident, $consts:ident, $Bits:ty) => {
impl PrimitiveFloat for $Float {
use_consts!(Self::{
DIGITS: u32,
EPSILON: Self,
INFINITY: Self,
MANTISSA_DIGITS: u32,
MAX: Self,
MAX_10_EXP: i32,
MAX_EXP: i32,
MIN: Self,
MIN_10_EXP: i32,
MIN_EXP: i32,
MIN_POSITIVE: Self,
NAN: Self,
NEG_INFINITY: Self,
RADIX: u32,
});
use_consts!($consts::{
E: Self,
EULER_GAMMA: Self,
FRAC_1_PI: Self,
FRAC_1_SQRT_2: Self,
FRAC_2_PI: Self,
FRAC_2_SQRT_PI: Self,
FRAC_PI_2: Self,
FRAC_PI_3: Self,
FRAC_PI_4: Self,
FRAC_PI_6: Self,
FRAC_PI_8: Self,
GOLDEN_RATIO: Self,
LN_2: Self,
LN_10: Self,
LOG2_10: Self,
LOG2_E: Self,
LOG10_2: Self,
LOG10_E: Self,
PI: Self,
SQRT_2: Self,
TAU: Self,
});
type Bits = $Bits;
forward! {
fn from_bits(value: Self::Bits) -> Self;
}
forward! {
fn abs(self) -> Self;
fn clamp(self, min: Self, max: Self) -> Self;
fn classify(self) -> FpCategory;
fn copysign(self, sign: Self) -> Self;
fn is_finite(self) -> bool;
fn is_infinite(self) -> bool;
fn is_nan(self) -> bool;
fn is_normal(self) -> bool;
fn is_sign_negative(self) -> bool;
fn is_sign_positive(self) -> bool;
fn is_subnormal(self) -> bool;
fn max(self, other: Self) -> Self;
fn min(self, other: Self) -> Self;
fn next_down(self) -> Self;
fn next_up(self) -> Self;
fn recip(self) -> Self;
fn signum(self) -> Self;
fn to_bits(self) -> Self::Bits;
fn to_degrees(self) -> Self;
fn to_radians(self) -> Self;
}
forward! {
fn total_cmp(&self, other: &Self) -> Ordering;
}
#[doc = forward_doc!(to_int_unchecked)]
#[inline]
unsafe fn to_int_unchecked<Int>(self) -> Int
where
Self: PrimitiveFloatToInt<Int>,
{
unsafe { <Self as PrimitiveFloatToInt<Int>>::__to_int_unchecked(self, SealedToken) }
}
#[cfg(feature = "std")]
forward! {
fn acos(self) -> Self;
fn acosh(self) -> Self;
fn asin(self) -> Self;
fn asinh(self) -> Self;
fn atan(self) -> Self;
fn atan2(self, other: Self) -> Self;
fn atanh(self) -> Self;
fn cbrt(self) -> Self;
fn ceil(self) -> Self;
fn cos(self) -> Self;
fn cosh(self) -> Self;
fn div_euclid(self, rhs: Self) -> Self;
fn exp(self) -> Self;
fn exp2(self) -> Self;
fn exp_m1(self) -> Self;
fn floor(self) -> Self;
fn fract(self) -> Self;
fn hypot(self, other: Self) -> Self;
fn ln(self) -> Self;
fn ln_1p(self) -> Self;
fn log(self, base: Self) -> Self;
fn log2(self) -> Self;
fn log10(self) -> Self;
fn mul_add(self, a: Self, b: Self) -> Self;
fn powf(self, n: Self) -> Self;
fn powi(self, n: i32) -> Self;
fn rem_euclid(self, rhs: Self) -> Self;
fn round(self) -> Self;
fn round_ties_even(self) -> Self;
fn sin(self) -> Self;
fn sin_cos(self) -> (Self, Self);
fn sinh(self) -> Self;
fn sqrt(self) -> Self;
fn tan(self) -> Self;
fn tanh(self) -> Self;
fn trunc(self) -> Self;
}
}
impl PrimitiveFloatRef<$Float> for &$Float {}
}
}
impl_float!(f32, f32_consts, u32);
impl_float!(f64, f64_consts, u64);
mod internal {
macro_rules! impl_float_to_int {
($Float:ty => $($Int:ty),+) => {
$(
impl super::PrimitiveFloatToInt<$Int> for $Float {
#[inline]
#[expect(private_interfaces)]
unsafe fn __to_int_unchecked(x: Self, _: super::SealedToken) -> $Int {
unsafe { <$Float>::to_int_unchecked::<$Int>(x) }
}
}
)+
}
}
impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
}