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