@@ -48,12 +48,8 @@ macro_rules! int {
4848int ! ( u16 , u32 , u64 ) ;
4949
5050/// A helper trait to avoid duplicating basically all the conversion code for IEEE floats.
51- ///
52- /// See the parent module's doc comment for why this is necessary.
53- ///
54- /// Should **never ever** be implemented for other types or be used outside the `dec2flt` module.
5551#[ doc( hidden) ]
56- pub trait RawFloat :
52+ pub trait Float :
5753 Sized
5854 + Div < Output = Self >
5955 + Neg < Output = Self >
@@ -128,8 +124,6 @@ pub trait RawFloat:
128124 const MIN_EXPONENT_ROUND_TO_EVEN : i32 ;
129125 const MAX_EXPONENT_ROUND_TO_EVEN : i32 ;
130126
131- /* limits related to Fast pathing */
132-
133127 /// Largest decimal exponent for a non-infinite value.
134128 ///
135129 /// This is the max exponent in binary converted to the max exponent in decimal. Allows fast
@@ -151,41 +145,19 @@ pub trait RawFloat:
151145 /// compile time since intermediates exceed the range of an `f64`.
152146 const SMALLEST_POWER_OF_TEN : i32 ;
153147
154- /// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
155- // assuming FLT_EVAL_METHOD = 0
156- 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- /// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
162- const MIN_EXPONENT_FAST_PATH : i64 = -Self :: MAX_EXPONENT_FAST_PATH ;
163-
164- /// Maximum exponent that can be represented for a disguised-fast path case.
165- /// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
166- 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- /// Maximum mantissa for the fast-path (`1 << 53` for f64).
170- const MAX_MANTISSA_FAST_PATH : u64 = 1 << Self :: SIG_TOTAL_BITS ;
171-
172- /// Converts integer into float through an as cast.
173- /// This is only called in the fast-path algorithm, and therefore
174- /// will not lose precision, since the value will always have
175- /// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
176- fn from_u64 ( v : u64 ) -> Self ;
177-
178- /// Performs a raw transmutation from an integer.
179- fn from_u64_bits ( v : u64 ) -> Self ;
180-
181- /// Gets a small power-of-ten for fast-path multiplication.
182- fn pow10_fast_path ( exponent : usize ) -> Self ;
183-
184148 /// Returns the category that this number falls into.
185149 fn classify ( self ) -> FpCategory ;
186150
187151 /// Transmute to the integer representation
188152 fn to_bits ( self ) -> Self :: Int ;
153+ }
154+
155+ /// Items that ideally would be on `Float`, but don't apply to all float types because they
156+ /// rely on the mantissa fitting into a `u64` (which isn't true for `f128`).
157+ #[ doc( hidden) ]
158+ pub trait FloatExt : Float {
159+ /// Performs a raw transmutation from an integer.
160+ fn from_u64_bits ( v : u64 ) -> Self ;
189161
190162 /// Returns the mantissa, exponent and sign as integers.
191163 ///
@@ -212,14 +184,49 @@ pub trait RawFloat:
212184 }
213185}
214186
187+ /// Extension to `Float` that are necessary for parsing using the Lemire method.
188+ ///
189+ /// See the parent module's doc comment for why this is necessary.
190+ ///
191+ /// Not intended for use outside of the `dec2flt` module.
192+ #[ doc( hidden) ]
193+ pub trait Lemire : FloatExt {
194+ /// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
195+ // assuming FLT_EVAL_METHOD = 0
196+ const MAX_EXPONENT_FAST_PATH : i64 = {
197+ let log2_5 = f64:: consts:: LOG2_10 - 1.0 ;
198+ ( Self :: SIG_TOTAL_BITS as f64 / log2_5) as i64
199+ } ;
200+
201+ /// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
202+ const MIN_EXPONENT_FAST_PATH : i64 = -Self :: MAX_EXPONENT_FAST_PATH ;
203+
204+ /// Maximum exponent that can be represented for a disguised-fast path case.
205+ /// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
206+ const MAX_EXPONENT_DISGUISED_FAST_PATH : i64 =
207+ Self :: MAX_EXPONENT_FAST_PATH + ( Self :: SIG_TOTAL_BITS as f64 / f64:: consts:: LOG2_10 ) as i64 ;
208+
209+ /// Maximum mantissa for the fast-path (`1 << 53` for f64).
210+ const MAX_MANTISSA_FAST_PATH : u64 = 1 << Self :: SIG_TOTAL_BITS ;
211+
212+ /// Gets a small power-of-ten for fast-path multiplication.
213+ fn pow10_fast_path ( exponent : usize ) -> Self ;
214+
215+ /// Converts integer into float through an as cast.
216+ /// This is only called in the fast-path algorithm, and therefore
217+ /// will not lose precision, since the value will always have
218+ /// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
219+ fn from_u64 ( v : u64 ) -> Self ;
220+ }
221+
215222/// Solve for `b` in `10^b = 2^a`
216223const fn pow2_to_pow10 ( a : i64 ) -> i64 {
217224 let res = ( a as f64 ) / f64:: consts:: LOG2_10 ;
218225 res as i64
219226}
220227
221228#[ cfg( target_has_reliable_f16) ]
222- impl RawFloat for f16 {
229+ impl Float for f16 {
223230 type Int = u16 ;
224231
225232 const INFINITY : Self = Self :: INFINITY ;
@@ -236,33 +243,39 @@ impl RawFloat for f16 {
236243 const MAX_EXPONENT_ROUND_TO_EVEN : i32 = 5 ;
237244 const SMALLEST_POWER_OF_TEN : i32 = -27 ;
238245
239- #[ inline]
240- fn from_u64 ( v : u64 ) -> Self {
241- debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
242- v as _
246+ fn to_bits ( self ) -> Self :: Int {
247+ self . to_bits ( )
248+ }
249+
250+ fn classify ( self ) -> FpCategory {
251+ self . classify ( )
243252 }
253+ }
244254
255+ #[ cfg( target_has_reliable_f16) ]
256+ impl FloatExt for f16 {
245257 #[ inline]
246258 fn from_u64_bits ( v : u64 ) -> Self {
247259 Self :: from_bits ( ( v & 0xFFFF ) as u16 )
248260 }
261+ }
249262
263+ #[ cfg( target_has_reliable_f16) ]
264+ impl Lemire for f16 {
250265 fn pow10_fast_path ( exponent : usize ) -> Self {
251266 #[ allow( clippy:: use_self) ]
252267 const TABLE : [ f16 ; 8 ] = [ 1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 0.0 , 0.0 , 0. ] ;
253268 TABLE [ exponent & 7 ]
254269 }
255270
256- fn to_bits ( self ) -> Self :: Int {
257- self . to_bits ( )
258- }
259-
260- fn classify ( self ) -> FpCategory {
261- self . classify ( )
271+ #[ inline]
272+ fn from_u64 ( v : u64 ) -> Self {
273+ debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
274+ v as _
262275 }
263276}
264277
265- impl RawFloat for f32 {
278+ impl Float for f32 {
266279 type Int = u32 ;
267280
268281 const INFINITY : Self = f32:: INFINITY ;
@@ -279,34 +292,38 @@ impl RawFloat for f32 {
279292 const MAX_EXPONENT_ROUND_TO_EVEN : i32 = 10 ;
280293 const SMALLEST_POWER_OF_TEN : i32 = -65 ;
281294
282- #[ inline]
283- fn from_u64 ( v : u64 ) -> Self {
284- debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
285- v as _
295+ fn to_bits ( self ) -> Self :: Int {
296+ self . to_bits ( )
286297 }
287298
299+ fn classify ( self ) -> FpCategory {
300+ self . classify ( )
301+ }
302+ }
303+
304+ impl FloatExt for f32 {
288305 #[ inline]
289306 fn from_u64_bits ( v : u64 ) -> Self {
290307 f32:: from_bits ( ( v & 0xFFFFFFFF ) as u32 )
291308 }
309+ }
292310
311+ impl Lemire for f32 {
293312 fn pow10_fast_path ( exponent : usize ) -> Self {
294313 #[ allow( clippy:: use_self) ]
295314 const TABLE : [ f32 ; 16 ] =
296315 [ 1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 1e5 , 1e6 , 1e7 , 1e8 , 1e9 , 1e10 , 0. , 0. , 0. , 0. , 0. ] ;
297316 TABLE [ exponent & 15 ]
298317 }
299318
300- fn to_bits ( self ) -> Self :: Int {
301- self . to_bits ( )
302- }
303-
304- fn classify ( self ) -> FpCategory {
305- self . classify ( )
319+ #[ inline]
320+ fn from_u64 ( v : u64 ) -> Self {
321+ debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
322+ v as _
306323 }
307324}
308325
309- impl RawFloat for f64 {
326+ impl Float for f64 {
310327 type Int = u64 ;
311328
312329 const INFINITY : Self = Self :: INFINITY ;
@@ -323,17 +340,23 @@ impl RawFloat for f64 {
323340 const MAX_EXPONENT_ROUND_TO_EVEN : i32 = 23 ;
324341 const SMALLEST_POWER_OF_TEN : i32 = -342 ;
325342
326- #[ inline]
327- fn from_u64 ( v : u64 ) -> Self {
328- debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
329- v as _
343+ fn to_bits ( self ) -> Self :: Int {
344+ self . to_bits ( )
330345 }
331346
347+ fn classify ( self ) -> FpCategory {
348+ self . classify ( )
349+ }
350+ }
351+
352+ impl FloatExt for f64 {
332353 #[ inline]
333354 fn from_u64_bits ( v : u64 ) -> Self {
334355 f64:: from_bits ( v)
335356 }
357+ }
336358
359+ impl Lemire for f64 {
337360 fn pow10_fast_path ( exponent : usize ) -> Self {
338361 const TABLE : [ f64 ; 32 ] = [
339362 1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 1e5 , 1e6 , 1e7 , 1e8 , 1e9 , 1e10 , 1e11 , 1e12 , 1e13 , 1e14 , 1e15 ,
@@ -342,11 +365,9 @@ impl RawFloat for f64 {
342365 TABLE [ exponent & 31 ]
343366 }
344367
345- fn to_bits ( self ) -> Self :: Int {
346- self . to_bits ( )
347- }
348-
349- fn classify ( self ) -> FpCategory {
350- self . classify ( )
368+ #[ inline]
369+ fn from_u64 ( v : u64 ) -> Self {
370+ debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
371+ v as _
351372 }
352373}
0 commit comments