core/num/dec2flt/
float.rs
1use 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}