core/num/dec2flt/
float.rs1use crate::fmt::{Debug, LowerExp};
4use crate::num::FpCategory;
5use crate::ops::{Add, Div, Mul, Neg};
6
7#[doc(hidden)]
13pub trait RawFloat:
14    Sized
15    + Div<Output = Self>
16    + Neg<Output = Self>
17    + Mul<Output = Self>
18    + Add<Output = Self>
19    + LowerExp
20    + PartialEq
21    + PartialOrd
22    + Default
23    + Clone
24    + Copy
25    + Debug
26{
27    const INFINITY: Self;
28    const NEG_INFINITY: Self;
29    const NAN: Self;
30    const NEG_NAN: Self;
31
32    const MANTISSA_EXPLICIT_BITS: usize;
34
35    const MIN_EXPONENT_ROUND_TO_EVEN: i32;
54    const MAX_EXPONENT_ROUND_TO_EVEN: i32;
55
56    const MIN_EXPONENT_FAST_PATH: i64;
58
59    const MAX_EXPONENT_FAST_PATH: i64;
61
62    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64;
65
66    const MINIMUM_EXPONENT: i32;
68
69    const INFINITE_POWER: i32;
71
72    const SIGN_INDEX: usize;
74
75    const SMALLEST_POWER_OF_TEN: i32;
77
78    const LARGEST_POWER_OF_TEN: i32;
80
81    const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS;
83
84    fn from_u64(v: u64) -> Self;
89
90    fn from_u64_bits(v: u64) -> Self;
92
93    fn pow10_fast_path(exponent: usize) -> Self;
95
96    fn classify(self) -> FpCategory;
98
99    fn integer_decode(self) -> (u64, i16, i8);
101}
102
103impl RawFloat for f32 {
104    const INFINITY: Self = f32::INFINITY;
105    const NEG_INFINITY: Self = f32::NEG_INFINITY;
106    const NAN: Self = f32::NAN;
107    const NEG_NAN: Self = -f32::NAN;
108
109    const MANTISSA_EXPLICIT_BITS: usize = 23;
110    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
111    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
112    const MIN_EXPONENT_FAST_PATH: i64 = -10; const MAX_EXPONENT_FAST_PATH: i64 = 10;
114    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17;
115    const MINIMUM_EXPONENT: i32 = -127;
116    const INFINITE_POWER: i32 = 0xFF;
117    const SIGN_INDEX: usize = 31;
118    const SMALLEST_POWER_OF_TEN: i32 = -65;
119    const LARGEST_POWER_OF_TEN: i32 = 38;
120
121    #[inline]
122    fn from_u64(v: u64) -> Self {
123        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
124        v as _
125    }
126
127    #[inline]
128    fn from_u64_bits(v: u64) -> Self {
129        f32::from_bits((v & 0xFFFFFFFF) as u32)
130    }
131
132    fn pow10_fast_path(exponent: usize) -> Self {
133        #[allow(clippy::use_self)]
134        const TABLE: [f32; 16] =
135            [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
136        TABLE[exponent & 15]
137    }
138
139    fn integer_decode(self) -> (u64, i16, i8) {
141        let bits = self.to_bits();
142        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
143        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
144        let mantissa =
145            if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
146        exponent -= 127 + 23;
148        (mantissa as u64, exponent, sign)
149    }
150
151    fn classify(self) -> FpCategory {
152        self.classify()
153    }
154}
155
156impl RawFloat for f64 {
157    const INFINITY: Self = f64::INFINITY;
158    const NEG_INFINITY: Self = f64::NEG_INFINITY;
159    const NAN: Self = f64::NAN;
160    const NEG_NAN: Self = -f64::NAN;
161
162    const MANTISSA_EXPLICIT_BITS: usize = 52;
163    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
164    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
165    const MIN_EXPONENT_FAST_PATH: i64 = -22; const MAX_EXPONENT_FAST_PATH: i64 = 22;
167    const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 37;
168    const MINIMUM_EXPONENT: i32 = -1023;
169    const INFINITE_POWER: i32 = 0x7FF;
170    const SIGN_INDEX: usize = 63;
171    const SMALLEST_POWER_OF_TEN: i32 = -342;
172    const LARGEST_POWER_OF_TEN: i32 = 308;
173
174    #[inline]
175    fn from_u64(v: u64) -> Self {
176        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
177        v as _
178    }
179
180    #[inline]
181    fn from_u64_bits(v: u64) -> Self {
182        f64::from_bits(v)
183    }
184
185    fn pow10_fast_path(exponent: usize) -> Self {
186        const TABLE: [f64; 32] = [
187            1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
188            1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
189        ];
190        TABLE[exponent & 31]
191    }
192
193    fn integer_decode(self) -> (u64, i16, i8) {
195        let bits = self.to_bits();
196        let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
197        let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
198        let mantissa = if exponent == 0 {
199            (bits & 0xfffffffffffff) << 1
200        } else {
201            (bits & 0xfffffffffffff) | 0x10000000000000
202        };
203        exponent -= 1023 + 52;
205        (mantissa, exponent, sign)
206    }
207
208    fn classify(self) -> FpCategory {
209        self.classify()
210    }
211}