const_soft_float/soft_f64/
mod.rs

1pub(crate) mod helpers;
2
3pub mod add;
4pub mod cmp;
5pub mod copysign;
6pub mod cos;
7pub mod div;
8pub mod floor;
9pub mod mul;
10pub mod pow;
11pub mod round;
12pub mod sin;
13pub mod sqrt;
14pub mod trunc;
15
16#[cfg(feature = "const_trait_impl")]
17pub mod const_impl_trait;
18
19#[cfg(feature = "const_trait_impl")]
20pub use const_impl_trait as impl_trait;
21
22#[cfg(not(feature = "const_trait_impl"))]
23pub mod impl_trait;
24
25#[derive(Default, Copy, Clone)]
26#[repr(transparent)]
27pub struct SoftF64(pub f64);
28
29impl SoftF64 {
30    pub const fn from_f64(a: f64) -> Self {
31        Self(a)
32    }
33
34    pub const fn to_f64(self) -> f64 {
35        self.0
36    }
37
38    pub const fn from_bits(a: u64) -> Self {
39        Self(unsafe { core::mem::transmute(a) })
40    }
41
42    pub const fn to_bits(self) -> u64 {
43        unsafe { core::mem::transmute(self.0) }
44    }
45
46    pub const fn add(self, rhs: Self) -> Self {
47        add::add(self, rhs)
48    }
49
50    pub const fn mul(self, rhs: Self) -> Self {
51        mul::mul(self, rhs)
52    }
53
54    pub const fn div(self, rhs: Self) -> Self {
55        div::div(self, rhs)
56    }
57
58    pub const fn cmp(self, rhs: Self) -> Option<core::cmp::Ordering> {
59        cmp::cmp(self, rhs)
60    }
61
62    pub const fn neg(self) -> Self {
63        Self::from_repr(self.repr() ^ Self::SIGN_MASK)
64    }
65
66    pub const fn sub(self, rhs: Self) -> Self {
67        self.add(rhs.neg())
68    }
69
70    pub const fn sqrt(self) -> Self {
71        sqrt::sqrt(self)
72    }
73
74    pub const fn powi(self, n: i32) -> Self {
75        pow::pow(self, n)
76    }
77
78    pub const fn copysign(self, other: Self) -> Self {
79        copysign::copysign(self, other)
80    }
81
82    pub const fn trunc(self) -> Self {
83        trunc::trunc(self)
84    }
85
86    pub const fn round(self) -> Self {
87        round::round(self)
88    }
89
90    pub const fn floor(self) -> Self {
91        floor::floor(self)
92    }
93
94    pub const fn sin(self) -> Self {
95        sin::sin(self)
96    }
97
98    pub const fn cos(self) -> Self {
99        cos::cos(self)
100    }
101}
102
103type SelfInt = u64;
104type SelfSignedInt = i64;
105type SelfExpInt = i16;
106
107#[allow(unused)]
108impl SoftF64 {
109    const ZERO: Self = Self(0.0);
110    const ONE: Self = Self(1.0);
111    const BITS: u32 = 64;
112    const SIGNIFICAND_BITS: u32 = 52;
113    const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1;
114    const EXPONENT_MAX: u32 = (1 << Self::EXPONENT_BITS) - 1;
115    const EXPONENT_BIAS: u32 = Self::EXPONENT_MAX >> 1;
116    const SIGN_MASK: SelfInt = 1 << (Self::BITS - 1);
117    const SIGNIFICAND_MASK: SelfInt = (1 << Self::SIGNIFICAND_BITS) - 1;
118    const IMPLICIT_BIT: SelfInt = 1 << Self::SIGNIFICAND_BITS;
119    const EXPONENT_MASK: SelfInt = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);
120
121    const fn repr(self) -> SelfInt {
122        self.to_bits()
123    }
124    const fn signed_repr(self) -> SelfSignedInt {
125        self.to_bits() as SelfSignedInt
126    }
127    const fn sign(self) -> bool {
128        self.signed_repr() < 0
129    }
130    const fn exp(self) -> SelfExpInt {
131        ((self.to_bits() & Self::EXPONENT_MASK) >> Self::SIGNIFICAND_BITS) as SelfExpInt
132    }
133    const fn frac(self) -> SelfInt {
134        self.to_bits() & Self::SIGNIFICAND_MASK
135    }
136    const fn imp_frac(self) -> SelfInt {
137        self.frac() | Self::IMPLICIT_BIT
138    }
139    const fn from_repr(a: SelfInt) -> Self {
140        Self::from_bits(a)
141    }
142    const fn from_parts(sign: bool, exponent: SelfInt, significand: SelfInt) -> Self {
143        Self::from_repr(
144            ((sign as SelfInt) << (Self::BITS - 1))
145                | ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK)
146                | (significand & Self::SIGNIFICAND_MASK),
147        )
148    }
149    const fn normalize(significand: SelfInt) -> (i32, SelfInt) {
150        let shift = significand
151            .leading_zeros()
152            .wrapping_sub((1u64 << Self::SIGNIFICAND_BITS).leading_zeros());
153        (
154            1i32.wrapping_sub(shift as i32),
155            significand << shift as SelfInt,
156        )
157    }
158    const fn is_subnormal(self) -> bool {
159        (self.repr() & Self::EXPONENT_MASK) == 0
160    }
161
162    const fn scalbn(self, n: i32) -> SoftF64 {
163        helpers::scalbn(self, n)
164    }
165}
166
167const fn u128_lo(x: u128) -> u64 {
168    x as u64
169}
170
171const fn u128_hi(x: u128) -> u64 {
172    (x >> 64) as u64
173}
174
175const fn u64_widen_mul(a: u64, b: u64) -> (u64, u64) {
176    let x = u128::wrapping_mul(a as _, b as _);
177    (u128_lo(x), u128_hi(x))
178}