const_soft_float/soft_f32/
mod.rs1mod 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 SoftF32(pub f32);
28
29impl SoftF32 {
30 pub const fn from_f32(a: f32) -> Self {
31 Self(a)
32 }
33
34 pub const fn to_f32(self) -> f32 {
35 self.0
36 }
37
38 pub const fn from_bits(a: u32) -> Self {
39 Self(unsafe { core::mem::transmute(a) })
40 }
41
42 pub const fn to_bits(self) -> u32 {
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::sqrtf(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::sinf(self)
96 }
97
98 pub const fn cos(self) -> Self {
99 cos::cos(self)
100 }
101}
102
103type SelfInt = u32;
104type SelfSignedInt = i32;
105type SelfExpInt = i16;
106
107#[allow(unused)]
108impl SoftF32 {
109 const ZERO: Self = Self(0.0);
110 const ONE: Self = Self(1.0);
111 const BITS: u32 = 32;
112 const SIGNIFICAND_BITS: u32 = 23;
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((1u32 << 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
163const fn u64_lo(x: u64) -> u32 {
164 x as u32
165}
166
167const fn u64_hi(x: u64) -> u32 {
168 (x >> 32) as u32
169}
170
171const fn u32_widen_mul(a: u32, b: u32) -> (u32, u32) {
172 let x = u64::wrapping_mul(a as _, b as _);
173 (u64_lo(x), u64_hi(x))
174}