core/num/dec2flt/
float.rs1use core::f64;
4
5use crate::fmt::{Debug, LowerExp};
6use crate::num::FpCategory;
7use crate::ops::{self, Add, Div, Mul, Neg};
8
9pub trait CastInto<T: Copy>: Copy {
11 fn cast(self) -> T;
12}
13
14pub trait Integer:
16 Sized
17 + Clone
18 + Copy
19 + Debug
20 + ops::Shr<u32, Output = Self>
21 + ops::Shl<u32, Output = Self>
22 + ops::BitAnd<Output = Self>
23 + ops::BitOr<Output = Self>
24 + PartialEq
25 + CastInto<i16>
26{
27 const ZERO: Self;
28 const ONE: Self;
29}
30
31macro_rules! int {
32 ($($ty:ty),+) => {
33 $(
34 impl CastInto<i16> for $ty {
35 fn cast(self) -> i16 {
36 self as i16
37 }
38 }
39
40 impl Integer for $ty {
41 const ZERO: Self = 0;
42 const ONE: Self = 1;
43 }
44 )+
45 }
46}
47
48int!(u16, u32, u64);
49
50#[doc(hidden)]
56pub trait RawFloat:
57 Sized
58 + Div<Output = Self>
59 + Neg<Output = Self>
60 + Mul<Output = Self>
61 + Add<Output = Self>
62 + LowerExp
63 + PartialEq
64 + PartialOrd
65 + Default
66 + Clone
67 + Copy
68 + Debug
69{
70 type Int: Integer + Into<u64>;
72
73 const INFINITY: Self;
76 const NEG_INFINITY: Self;
77 const NAN: Self;
78 const NEG_NAN: Self;
79
80 const BITS: u32;
82
83 const SIG_TOTAL_BITS: u32;
85
86 const EXP_MASK: Self::Int;
87 const SIG_MASK: Self::Int;
88
89 const SIG_BITS: u32 = Self::SIG_TOTAL_BITS - 1;
91
92 const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
94
95 const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
100
101 const INFINITE_POWER: i32 = Self::EXP_SAT as i32;
103
104 const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
106
107 const EXP_MIN: i32 = -(Self::EXP_BIAS as i32 - 1);
109
110 const MIN_EXPONENT_ROUND_TO_EVEN: i32;
129 const MAX_EXPONENT_ROUND_TO_EVEN: i32;
130
131 const LARGEST_POWER_OF_TEN: i32 = {
138 let largest_pow2 = Self::EXP_BIAS + 1;
139 pow2_to_pow10(largest_pow2 as i64) as i32
140 };
141
142 const SMALLEST_POWER_OF_TEN: i32;
153
154 const MAX_EXPONENT_FAST_PATH: i64 = {
157 let log2_5 = f64::consts::LOG2_10 - 1.0;
158 (Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
159 };
160
161 const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
163
164 const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
167 Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
168
169 const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
171
172 fn from_u64(v: u64) -> Self;
177
178 fn from_u64_bits(v: u64) -> Self;
180
181 fn pow10_fast_path(exponent: usize) -> Self;
183
184 fn classify(self) -> FpCategory;
186
187 fn to_bits(self) -> Self::Int;
189
190 fn integer_decode(self) -> (u64, i16, i8) {
201 let bits = self.to_bits();
202 let sign: i8 = if bits >> (Self::BITS - 1) == Self::Int::ZERO { 1 } else { -1 };
203 let mut exponent: i16 = ((bits & Self::EXP_MASK) >> Self::SIG_BITS).cast();
204 let mantissa = if exponent == 0 {
205 (bits & Self::SIG_MASK) << 1
206 } else {
207 (bits & Self::SIG_MASK) | (Self::Int::ONE << Self::SIG_BITS)
208 };
209 exponent -= (Self::EXP_BIAS + Self::SIG_BITS) as i16;
211 (mantissa.into(), exponent, sign)
212 }
213}
214
215const fn pow2_to_pow10(a: i64) -> i64 {
217 let res = (a as f64) / f64::consts::LOG2_10;
218 res as i64
219}
220
221#[cfg(target_has_reliable_f16)]
222impl RawFloat for f16 {
223 type Int = u16;
224
225 const INFINITY: Self = Self::INFINITY;
226 const NEG_INFINITY: Self = Self::NEG_INFINITY;
227 const NAN: Self = Self::NAN;
228 const NEG_NAN: Self = -Self::NAN;
229
230 const BITS: u32 = 16;
231 const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
232 const EXP_MASK: Self::Int = Self::EXP_MASK;
233 const SIG_MASK: Self::Int = Self::MAN_MASK;
234
235 const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -22;
236 const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 5;
237 const SMALLEST_POWER_OF_TEN: i32 = -27;
238
239 #[inline]
240 fn from_u64(v: u64) -> Self {
241 debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
242 v as _
243 }
244
245 #[inline]
246 fn from_u64_bits(v: u64) -> Self {
247 Self::from_bits((v & 0xFFFF) as u16)
248 }
249
250 fn pow10_fast_path(exponent: usize) -> Self {
251 #[allow(clippy::use_self)]
252 const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
253 TABLE[exponent & 7]
254 }
255
256 fn to_bits(self) -> Self::Int {
257 self.to_bits()
258 }
259
260 fn classify(self) -> FpCategory {
261 self.classify()
262 }
263}
264
265impl RawFloat for f32 {
266 type Int = u32;
267
268 const INFINITY: Self = f32::INFINITY;
269 const NEG_INFINITY: Self = f32::NEG_INFINITY;
270 const NAN: Self = f32::NAN;
271 const NEG_NAN: Self = -f32::NAN;
272
273 const BITS: u32 = 32;
274 const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
275 const EXP_MASK: Self::Int = Self::EXP_MASK;
276 const SIG_MASK: Self::Int = Self::MAN_MASK;
277
278 const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
279 const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
280 const SMALLEST_POWER_OF_TEN: i32 = -65;
281
282 #[inline]
283 fn from_u64(v: u64) -> Self {
284 debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
285 v as _
286 }
287
288 #[inline]
289 fn from_u64_bits(v: u64) -> Self {
290 f32::from_bits((v & 0xFFFFFFFF) as u32)
291 }
292
293 fn pow10_fast_path(exponent: usize) -> Self {
294 #[allow(clippy::use_self)]
295 const TABLE: [f32; 16] =
296 [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
297 TABLE[exponent & 15]
298 }
299
300 fn to_bits(self) -> Self::Int {
301 self.to_bits()
302 }
303
304 fn classify(self) -> FpCategory {
305 self.classify()
306 }
307}
308
309impl RawFloat for f64 {
310 type Int = u64;
311
312 const INFINITY: Self = Self::INFINITY;
313 const NEG_INFINITY: Self = Self::NEG_INFINITY;
314 const NAN: Self = Self::NAN;
315 const NEG_NAN: Self = -Self::NAN;
316
317 const BITS: u32 = 64;
318 const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
319 const EXP_MASK: Self::Int = Self::EXP_MASK;
320 const SIG_MASK: Self::Int = Self::MAN_MASK;
321
322 const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
323 const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
324 const SMALLEST_POWER_OF_TEN: i32 = -342;
325
326 #[inline]
327 fn from_u64(v: u64) -> Self {
328 debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
329 v as _
330 }
331
332 #[inline]
333 fn from_u64_bits(v: u64) -> Self {
334 f64::from_bits(v)
335 }
336
337 fn pow10_fast_path(exponent: usize) -> Self {
338 const TABLE: [f64; 32] = [
339 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
340 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
341 ];
342 TABLE[exponent & 31]
343 }
344
345 fn to_bits(self) -> Self::Int {
346 self.to_bits()
347 }
348
349 fn classify(self) -> FpCategory {
350 self.classify()
351 }
352}