lexical_parse_float/
limits.rs

1//! Determine the limits of exact exponent and mantissas for floats.
2
3#![doc(hidden)]
4
5use lexical_util::assert::debug_assert_radix;
6#[cfg(feature = "f16")]
7use lexical_util::bf16::bf16;
8#[cfg(feature = "f16")]
9use lexical_util::f16::f16;
10
11// EXACT EXPONENT
12// --------------
13
14// Calculating the exponent limit requires determining the largest exponent
15// we can calculate for a radix that can be **exactly** store in the
16// float type. If the value is a power-of-two, then we simply
17// need to scale the minimum, denormal exp and maximum exp to the type
18// size. Otherwise, we need to calculate the number of digits
19// that can fit into the type's precision, after removing a power-of-two
20// (since these values can be represented exactly).
21//
22// The mantissa limit is the number of digits we can remove from
23// the exponent into the mantissa, and is therefore is the
24// `⌊ precision / log2(radix) ⌋`, where precision does not include
25// the hidden bit.
26//
27// The algorithm for calculating both `exponent_limit` and `mantissa_limit`,
28// in Python, can be done as follows:
29//
30// DO NOT MODIFY: Generated by `src/etc/limits.py`
31
32// EXACT FLOAT
33// -----------
34
35/// Get exact exponent limit for radix.
36#[doc(hidden)]
37pub trait ExactFloat {
38    /// Get min and max exponent limits (exact) from radix.
39    fn exponent_limit(radix: u32) -> (i64, i64);
40
41    /// Get the number of digits that can be shifted from exponent to mantissa.
42    fn mantissa_limit(radix: u32) -> i64;
43}
44
45impl ExactFloat for f32 {
46    #[inline(always)]
47    fn exponent_limit(radix: u32) -> (i64, i64) {
48        debug_assert_radix(radix);
49        f32_exponent_limit(radix)
50    }
51
52    #[inline(always)]
53    fn mantissa_limit(radix: u32) -> i64 {
54        debug_assert_radix(radix);
55        f32_mantissa_limit(radix)
56    }
57}
58
59impl ExactFloat for f64 {
60    #[inline(always)]
61    fn exponent_limit(radix: u32) -> (i64, i64) {
62        debug_assert_radix(radix);
63        f64_exponent_limit(radix)
64    }
65
66    #[inline(always)]
67    fn mantissa_limit(radix: u32) -> i64 {
68        debug_assert_radix(radix);
69        f64_mantissa_limit(radix)
70    }
71}
72
73#[cfg(feature = "f16")]
74impl ExactFloat for f16 {
75    #[inline(always)]
76    fn exponent_limit(_: u32) -> (i64, i64) {
77        unimplemented!()
78    }
79
80    #[inline(always)]
81    fn mantissa_limit(_: u32) -> i64 {
82        unimplemented!()
83    }
84}
85
86#[cfg(feature = "f16")]
87impl ExactFloat for bf16 {
88    #[inline(always)]
89    fn exponent_limit(_: u32) -> (i64, i64) {
90        unimplemented!()
91    }
92
93    #[inline(always)]
94    fn mantissa_limit(_: u32) -> i64 {
95        unimplemented!()
96    }
97}
98
99//#[cfg(feature = "f128")]
100//impl ExactFloat for f128 {
101//    #[inline(always)]
102//    fn exponent_limit(radix: u32) -> (i64, i64) {
103//        debug_assert_radix(radix);
104//        match radix {
105//            2 if cfg!(feature = "power-of-two") => (-16494, 16383),
106//            3 if cfg!(feature = "radix") => (-71, 71),
107//            4 if cfg!(feature = "power-of-two") => (-8247, 8191),
108//            5 if cfg!(feature = "radix") => (-48, 48),
109//            6 if cfg!(feature = "radix") => (-71, 71),
110//            7 if cfg!(feature = "radix") => (-40, 40),
111//            8 if cfg!(feature = "power-of-two") => (-5498, 5461),
112//            9 if cfg!(feature = "radix") => (-35, 35),
113//            10 => (-48, 48),
114//            11 if cfg!(feature = "radix") => (-32, 32),
115//            12 if cfg!(feature = "radix") => (-71, 71),
116//            13 if cfg!(feature = "radix") => (-30, 30),
117//            14 if cfg!(feature = "radix") => (-40, 40),
118//            15 if cfg!(feature = "radix") => (-28, 28),
119//            16 if cfg!(feature = "power-of-two") => (-4123, 4095),
120//            17 if cfg!(feature = "radix") => (-27, 27),
121//            18 if cfg!(feature = "radix") => (-35, 35),
122//            19 if cfg!(feature = "radix") => (-26, 26),
123//            20 if cfg!(feature = "radix") => (-48, 48),
124//            21 if cfg!(feature = "radix") => (-25, 25),
125//            22 if cfg!(feature = "radix") => (-32, 32),
126//            23 if cfg!(feature = "radix") => (-24, 24),
127//            24 if cfg!(feature = "radix") => (-71, 71),
128//            25 if cfg!(feature = "radix") => (-24, 24),
129//            26 if cfg!(feature = "radix") => (-30, 30),
130//            27 if cfg!(feature = "radix") => (-23, 23),
131//            28 if cfg!(feature = "radix") => (-40, 40),
132//            29 if cfg!(feature = "radix") => (-23, 23),
133//            30 if cfg!(feature = "radix") => (-28, 28),
134//            31 if cfg!(feature = "radix") => (-22, 22),
135//            32 if cfg!(feature = "power-of-two") => (-3298, 3276),
136//            33 if cfg!(feature = "radix") => (-22, 22),
137//            34 if cfg!(feature = "radix") => (-27, 27),
138//            35 if cfg!(feature = "radix") => (-22, 22),
139//            36 if cfg!(feature = "radix") => (-35, 35),
140//            // Invalid radix
141//            _ => unreachable!(),
142//        }
143//    }
144//
145//    #[inline(always)]
146//    fn mantissa_limit(radix: u32) -> i64 {
147//        debug_assert_radix(radix);
148//        match radix {
149//            2 if cfg!(feature = "power-of-two") => 113,
150//            3 if cfg!(feature = "radix") => 71,
151//            4 if cfg!(feature = "power-of-two") => 56,
152//            5 if cfg!(feature = "radix") => 48,
153//            6 if cfg!(feature = "radix") => 43,
154//            7 if cfg!(feature = "radix") => 40,
155//            8 if cfg!(feature = "power-of-two") => 37,
156//            9 if cfg!(feature = "radix") => 35,
157//            10 => 34,
158//            11 if cfg!(feature = "radix") => 32,
159//            12 if cfg!(feature = "radix") => 31,
160//            13 if cfg!(feature = "radix") => 30,
161//            14 if cfg!(feature = "radix") => 29,
162//            15 if cfg!(feature = "radix") => 28,
163//            16 if cfg!(feature = "power-of-two") => 28,
164//            17 if cfg!(feature = "radix") => 27,
165//            18 if cfg!(feature = "radix") => 27,
166//            19 if cfg!(feature = "radix") => 26,
167//            20 if cfg!(feature = "radix") => 26,
168//            21 if cfg!(feature = "radix") => 25,
169//            22 if cfg!(feature = "radix") => 25,
170//            23 if cfg!(feature = "radix") => 24,
171//            24 if cfg!(feature = "radix") => 24,
172//            25 if cfg!(feature = "radix") => 24,
173//            26 if cfg!(feature = "radix") => 24,
174//            27 if cfg!(feature = "radix") => 23,
175//            28 if cfg!(feature = "radix") => 23,
176//            29 if cfg!(feature = "radix") => 23,
177//            30 if cfg!(feature = "radix") => 23,
178//            31 if cfg!(feature = "radix") => 22,
179//            32 if cfg!(feature = "power-of-two") => 22,
180//            33 if cfg!(feature = "radix") => 22,
181//            34 if cfg!(feature = "radix") => 22,
182//            35 if cfg!(feature = "radix") => 22,
183//            36 if cfg!(feature = "radix") => 21,
184//            // Invalid radix
185//            _ => unreachable!(),
186//        }
187//    }
188//}
189
190// CONST FN
191// --------
192
193/// Get the exponent limit as a const fn.
194#[inline(always)]
195pub const fn f32_exponent_limit(radix: u32) -> (i64, i64) {
196    match radix {
197        2 if cfg!(feature = "power-of-two") => (-127, 127),
198        3 if cfg!(feature = "radix") => (-15, 15),
199        4 if cfg!(feature = "power-of-two") => (-63, 63),
200        5 if cfg!(feature = "radix") => (-10, 10),
201        6 if cfg!(feature = "radix") => (-15, 15),
202        7 if cfg!(feature = "radix") => (-8, 8),
203        8 if cfg!(feature = "power-of-two") => (-42, 42),
204        9 if cfg!(feature = "radix") => (-7, 7),
205        10 => (-10, 10),
206        11 if cfg!(feature = "radix") => (-6, 6),
207        12 if cfg!(feature = "radix") => (-15, 15),
208        13 if cfg!(feature = "radix") => (-6, 6),
209        14 if cfg!(feature = "radix") => (-8, 8),
210        15 if cfg!(feature = "radix") => (-6, 6),
211        16 if cfg!(feature = "power-of-two") => (-31, 31),
212        17 if cfg!(feature = "radix") => (-5, 5),
213        18 if cfg!(feature = "radix") => (-7, 7),
214        19 if cfg!(feature = "radix") => (-5, 5),
215        20 if cfg!(feature = "radix") => (-10, 10),
216        21 if cfg!(feature = "radix") => (-5, 5),
217        22 if cfg!(feature = "radix") => (-6, 6),
218        23 if cfg!(feature = "radix") => (-5, 5),
219        24 if cfg!(feature = "radix") => (-15, 15),
220        25 if cfg!(feature = "radix") => (-5, 5),
221        26 if cfg!(feature = "radix") => (-6, 6),
222        27 if cfg!(feature = "radix") => (-5, 5),
223        28 if cfg!(feature = "radix") => (-8, 8),
224        29 if cfg!(feature = "radix") => (-4, 4),
225        30 if cfg!(feature = "radix") => (-6, 6),
226        31 if cfg!(feature = "radix") => (-4, 4),
227        32 if cfg!(feature = "power-of-two") => (-25, 25),
228        33 if cfg!(feature = "radix") => (-4, 4),
229        34 if cfg!(feature = "radix") => (-5, 5),
230        35 if cfg!(feature = "radix") => (-4, 4),
231        36 if cfg!(feature = "radix") => (-7, 7),
232        _ => (0, 0),
233    }
234}
235
236/// Get the mantissa limit as a const fn.
237#[inline(always)]
238pub const fn f32_mantissa_limit(radix: u32) -> i64 {
239    match radix {
240        2 if cfg!(feature = "power-of-two") => 24,
241        3 if cfg!(feature = "radix") => 15,
242        4 if cfg!(feature = "power-of-two") => 12,
243        5 if cfg!(feature = "radix") => 10,
244        6 if cfg!(feature = "radix") => 9,
245        7 if cfg!(feature = "radix") => 8,
246        8 if cfg!(feature = "power-of-two") => 8,
247        9 if cfg!(feature = "radix") => 7,
248        10 => 7,
249        11 if cfg!(feature = "radix") => 6,
250        12 if cfg!(feature = "radix") => 6,
251        13 if cfg!(feature = "radix") => 6,
252        14 if cfg!(feature = "radix") => 6,
253        15 if cfg!(feature = "radix") => 6,
254        16 if cfg!(feature = "power-of-two") => 6,
255        17 if cfg!(feature = "radix") => 5,
256        18 if cfg!(feature = "radix") => 5,
257        19 if cfg!(feature = "radix") => 5,
258        20 if cfg!(feature = "radix") => 5,
259        21 if cfg!(feature = "radix") => 5,
260        22 if cfg!(feature = "radix") => 5,
261        23 if cfg!(feature = "radix") => 5,
262        24 if cfg!(feature = "radix") => 5,
263        25 if cfg!(feature = "radix") => 5,
264        26 if cfg!(feature = "radix") => 5,
265        27 if cfg!(feature = "radix") => 5,
266        28 if cfg!(feature = "radix") => 4,
267        29 if cfg!(feature = "radix") => 4,
268        30 if cfg!(feature = "radix") => 4,
269        31 if cfg!(feature = "radix") => 4,
270        32 if cfg!(feature = "power-of-two") => 4,
271        33 if cfg!(feature = "radix") => 4,
272        34 if cfg!(feature = "radix") => 4,
273        35 if cfg!(feature = "radix") => 4,
274        36 if cfg!(feature = "radix") => 4,
275        _ => 0,
276    }
277}
278
279/// Get the exponent limit as a const fn.
280#[inline(always)]
281pub const fn f64_exponent_limit(radix: u32) -> (i64, i64) {
282    match radix {
283        2 if cfg!(feature = "power-of-two") => (-1023, 1023),
284        3 if cfg!(feature = "radix") => (-33, 33),
285        4 if cfg!(feature = "power-of-two") => (-511, 511),
286        5 if cfg!(feature = "radix") => (-22, 22),
287        6 if cfg!(feature = "radix") => (-33, 33),
288        7 if cfg!(feature = "radix") => (-18, 18),
289        8 if cfg!(feature = "power-of-two") => (-341, 341),
290        9 if cfg!(feature = "radix") => (-16, 16),
291        10 => (-22, 22),
292        11 if cfg!(feature = "radix") => (-15, 15),
293        12 if cfg!(feature = "radix") => (-33, 33),
294        13 if cfg!(feature = "radix") => (-14, 14),
295        14 if cfg!(feature = "radix") => (-18, 18),
296        15 if cfg!(feature = "radix") => (-13, 13),
297        16 if cfg!(feature = "power-of-two") => (-255, 255),
298        17 if cfg!(feature = "radix") => (-12, 12),
299        18 if cfg!(feature = "radix") => (-16, 16),
300        19 if cfg!(feature = "radix") => (-12, 12),
301        20 if cfg!(feature = "radix") => (-22, 22),
302        21 if cfg!(feature = "radix") => (-12, 12),
303        22 if cfg!(feature = "radix") => (-15, 15),
304        23 if cfg!(feature = "radix") => (-11, 11),
305        24 if cfg!(feature = "radix") => (-33, 33),
306        25 if cfg!(feature = "radix") => (-11, 11),
307        26 if cfg!(feature = "radix") => (-14, 14),
308        27 if cfg!(feature = "radix") => (-11, 11),
309        28 if cfg!(feature = "radix") => (-18, 18),
310        29 if cfg!(feature = "radix") => (-10, 10),
311        30 if cfg!(feature = "radix") => (-13, 13),
312        31 if cfg!(feature = "radix") => (-10, 10),
313        32 if cfg!(feature = "power-of-two") => (-204, 204),
314        33 if cfg!(feature = "radix") => (-10, 10),
315        34 if cfg!(feature = "radix") => (-12, 12),
316        35 if cfg!(feature = "radix") => (-10, 10),
317        36 if cfg!(feature = "radix") => (-16, 16),
318        _ => (0, 0),
319    }
320}
321
322/// Get the mantissa limit as a const fn.
323#[inline(always)]
324pub const fn f64_mantissa_limit(radix: u32) -> i64 {
325    match radix {
326        2 if cfg!(feature = "power-of-two") => 53,
327        3 if cfg!(feature = "radix") => 33,
328        4 if cfg!(feature = "power-of-two") => 26,
329        5 if cfg!(feature = "radix") => 22,
330        6 if cfg!(feature = "radix") => 20,
331        7 if cfg!(feature = "radix") => 18,
332        8 if cfg!(feature = "power-of-two") => 17,
333        9 if cfg!(feature = "radix") => 16,
334        10 => 15,
335        11 if cfg!(feature = "radix") => 15,
336        12 if cfg!(feature = "radix") => 14,
337        13 if cfg!(feature = "radix") => 14,
338        14 if cfg!(feature = "radix") => 13,
339        15 if cfg!(feature = "radix") => 13,
340        16 if cfg!(feature = "power-of-two") => 13,
341        17 if cfg!(feature = "radix") => 12,
342        18 if cfg!(feature = "radix") => 12,
343        19 if cfg!(feature = "radix") => 12,
344        20 if cfg!(feature = "radix") => 12,
345        21 if cfg!(feature = "radix") => 12,
346        22 if cfg!(feature = "radix") => 11,
347        23 if cfg!(feature = "radix") => 11,
348        24 if cfg!(feature = "radix") => 11,
349        25 if cfg!(feature = "radix") => 11,
350        26 if cfg!(feature = "radix") => 11,
351        27 if cfg!(feature = "radix") => 11,
352        28 if cfg!(feature = "radix") => 11,
353        29 if cfg!(feature = "radix") => 10,
354        30 if cfg!(feature = "radix") => 10,
355        31 if cfg!(feature = "radix") => 10,
356        32 if cfg!(feature = "power-of-two") => 10,
357        33 if cfg!(feature = "radix") => 10,
358        34 if cfg!(feature = "radix") => 10,
359        35 if cfg!(feature = "radix") => 10,
360        36 if cfg!(feature = "radix") => 10,
361        _ => 0,
362    }
363}
364
365// POWER LIMITS
366// ------------
367
368//  The code used to generate these limits is as follows:
369//
370//  ```text
371//  import math
372//
373//  def find_power(base, max_value):
374//      '''Using log is unreliable, since it uses float math.'''
375//
376//      power = 0
377//      while base**power < max_value:
378//          power += 1
379//      return power - 1
380//
381//  def print_function(bits):
382//      print('#[inline(always)]')
383//      print(f'pub const fn u{bits}_power_limit(radix: u32) -> u32 {{')
384//      print('    match radix {')
385//      max_value = 2**bits - 1
386//      for radix in range(2, 37):
387//          power = find_power(radix, max_value)
388//          print(f'        {radix} => {power},')
389//      print('        // Any other radix should be unreachable.')
390//      print('        _ => 1,')
391//      print('    }')
392//      print('}')
393//      print('')
394//
395//  print_function(32)
396//  print_function(64)
397//  ```
398
399/// Get the maximum value for `radix^N` that can be represented in a u32.
400/// This is calculated as `⌊log(2^32 - 1, b)⌋`.
401#[inline(always)]
402pub const fn u32_power_limit(radix: u32) -> u32 {
403    match radix {
404        2 if cfg!(feature = "power-of-two") => 31,
405        3 if cfg!(feature = "radix") => 20,
406        4 if cfg!(feature = "power-of-two") => 15,
407        5 => 13,
408        6 if cfg!(feature = "radix") => 12,
409        7 if cfg!(feature = "radix") => 11,
410        8 if cfg!(feature = "power-of-two") => 10,
411        9 if cfg!(feature = "radix") => 10,
412        10 => 9,
413        11 if cfg!(feature = "radix") => 9,
414        12 if cfg!(feature = "radix") => 8,
415        13 if cfg!(feature = "radix") => 8,
416        14 if cfg!(feature = "radix") => 8,
417        15 if cfg!(feature = "radix") => 8,
418        16 if cfg!(feature = "power-of-two") => 7,
419        17 if cfg!(feature = "radix") => 7,
420        18 if cfg!(feature = "radix") => 7,
421        19 if cfg!(feature = "radix") => 7,
422        20 if cfg!(feature = "radix") => 7,
423        21 if cfg!(feature = "radix") => 7,
424        22 if cfg!(feature = "radix") => 7,
425        23 if cfg!(feature = "radix") => 7,
426        24 if cfg!(feature = "radix") => 6,
427        25 if cfg!(feature = "radix") => 6,
428        26 if cfg!(feature = "radix") => 6,
429        27 if cfg!(feature = "radix") => 6,
430        28 if cfg!(feature = "radix") => 6,
431        29 if cfg!(feature = "radix") => 6,
432        30 if cfg!(feature = "radix") => 6,
433        31 if cfg!(feature = "radix") => 6,
434        32 if cfg!(feature = "power-of-two") => 6,
435        33 if cfg!(feature = "radix") => 6,
436        34 if cfg!(feature = "radix") => 6,
437        35 if cfg!(feature = "radix") => 6,
438        36 if cfg!(feature = "radix") => 6,
439        // Any other radix should be unreachable.
440        _ => 1,
441    }
442}
443
444/// Get the maximum value for `radix^N` that can be represented in a u64.
445/// This is calculated as `⌊log(2^64 - 1, b)⌋`.
446#[inline(always)]
447pub const fn u64_power_limit(radix: u32) -> u32 {
448    match radix {
449        2 if cfg!(feature = "power-of-two") => 63,
450        3 if cfg!(feature = "radix") => 40,
451        4 if cfg!(feature = "power-of-two") => 31,
452        5 => 27,
453        6 if cfg!(feature = "radix") => 24,
454        7 if cfg!(feature = "radix") => 22,
455        8 if cfg!(feature = "power-of-two") => 21,
456        9 if cfg!(feature = "radix") => 20,
457        10 => 19,
458        11 if cfg!(feature = "radix") => 18,
459        12 if cfg!(feature = "radix") => 17,
460        13 if cfg!(feature = "radix") => 17,
461        14 if cfg!(feature = "radix") => 16,
462        15 if cfg!(feature = "radix") => 16,
463        16 if cfg!(feature = "power-of-two") => 15,
464        17 if cfg!(feature = "radix") => 15,
465        18 if cfg!(feature = "radix") => 15,
466        19 if cfg!(feature = "radix") => 15,
467        20 if cfg!(feature = "radix") => 14,
468        21 if cfg!(feature = "radix") => 14,
469        22 if cfg!(feature = "radix") => 14,
470        23 if cfg!(feature = "radix") => 14,
471        24 if cfg!(feature = "radix") => 13,
472        25 if cfg!(feature = "radix") => 13,
473        26 if cfg!(feature = "radix") => 13,
474        27 if cfg!(feature = "radix") => 13,
475        28 if cfg!(feature = "radix") => 13,
476        29 if cfg!(feature = "radix") => 13,
477        30 if cfg!(feature = "radix") => 13,
478        31 if cfg!(feature = "radix") => 12,
479        32 if cfg!(feature = "power-of-two") => 12,
480        33 if cfg!(feature = "radix") => 12,
481        34 if cfg!(feature = "radix") => 12,
482        35 if cfg!(feature = "radix") => 12,
483        36 if cfg!(feature = "radix") => 12,
484        // Any other radix should be unreachable.
485        _ => 1,
486    }
487}
488
489// MAX DIGITS
490// ----------
491
492/// Calculate the maximum number of digits possible in the mantissa.
493///
494/// Returns the maximum number of digits plus one.
495///
496/// We can exactly represent a float in radix `b` from radix 2 if
497/// `b` is divisible by 2. This function calculates the exact number of
498/// digits required to exactly represent that float. This makes sense,
499/// and the exact reference and I quote is:
500///
501///  > A necessary and sufficient condition for all numbers representable in radix β
502///  > with a finite number of digits to be representable in radix γ with a
503///  > finite number of digits is that β should divide an integer power of γ.
504///
505/// According to the "Handbook of Floating Point Arithmetic",
506/// for IEEE754, with emin being the min exponent, p2 being the
507/// precision, and b being the radix, the number of digits follows as:
508///
509/// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
510///
511/// For f16, this follows as:
512///     emin = -14
513///     p2 = 11
514///
515/// For bfloat16 , this follows as:
516///     emin = -126
517///     p2 = 8
518///
519/// For f32, this follows as:
520///     emin = -126
521///     p2 = 24
522///
523/// For f64, this follows as:
524///     emin = -1022
525///     p2 = 53
526///
527/// For f128, this follows as:
528///     emin = -16382
529///     p2 = 113
530///
531/// In Python:
532///     `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))`
533///
534/// This was used to calculate the maximum number of digits for [2, 36].
535///
536/// The minimum, denormal exponent can be calculated as follows: given
537/// the number of exponent bits `exp_bits`, and the number of bits
538/// in the mantissa `mantissa_bits`, we have an exponent bias
539/// `exp_bias` equal to `2^(exp_bits-1) - 1 + mantissa_bits`. We
540/// therefore have a denormal exponent `denormal_exp` equal to
541/// `1 - exp_bias` and the minimum, denormal float `min_float` is
542/// therefore `2^denormal_exp`.
543///
544/// For f16, this follows as:
545///     exp_bits = 5
546///     mantissa_bits = 10
547///     exp_bias = 25
548///     denormal_exp = -24
549///     min_float = 5.96 * 10^−8
550///
551/// For bfloat16, this follows as:
552///     exp_bits = 8
553///     mantissa_bits = 7
554///     exp_bias = 134
555///     denormal_exp = -133
556///     min_float = 9.18 * 10^−41
557///
558/// For f32, this follows as:
559///     exp_bits = 8
560///     mantissa_bits = 23
561///     exp_bias = 150
562///     denormal_exp = -149
563///     min_float = 1.40 * 10^−45
564///
565/// For f64, this follows as:
566///     exp_bits = 11
567///     mantissa_bits = 52
568///     exp_bias = 1075
569///     denormal_exp = -1074
570///     min_float = 5.00 * 10^−324
571///
572/// For f128, this follows as:
573///     exp_bits = 15
574///     mantissa_bits = 112
575///     exp_bias = 16495
576///     denormal_exp = -16494
577///     min_float = 6.48 * 10^−4966
578///
579/// These match statements can be generated with the following Python
580/// code:
581/// ```python
582/// import math
583///
584/// def digits(emin, p2, b):
585///     return -emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))
586///
587/// def max_digits(emin, p2):
588///     radices = [6, 10, 12, 14, 18, 20, 22, 24 26 28, 30, 34, 36]
589///     print('match radix {')
590///     for radix in radices:
591///         value = digits(emin, p2, radix)
592///         print(f'    {radix} => Some({value + 2}),')
593///     print('    // Powers of two should be unreachable.')
594///     print('    // Odd numbers will have infinite digits.')
595///     print('    _ => None,')
596///     print('}')
597/// ```
598pub trait MaxDigits {
599    fn max_digits(radix: u32) -> Option<usize>;
600}
601
602/// emin = -126
603/// p2 = 24
604impl MaxDigits for f32 {
605    #[inline(always)]
606    fn max_digits(radix: u32) -> Option<usize> {
607        debug_assert_radix(radix);
608        f32_max_digits(radix)
609    }
610}
611
612/// emin = -1022
613/// p2 = 53
614impl MaxDigits for f64 {
615    #[inline(always)]
616    fn max_digits(radix: u32) -> Option<usize> {
617        debug_assert_radix(radix);
618        f64_max_digits(radix)
619    }
620}
621
622#[cfg(feature = "f16")]
623impl MaxDigits for f16 {
624    #[inline(always)]
625    fn max_digits(_: u32) -> Option<usize> {
626        unimplemented!()
627    }
628}
629
630#[cfg(feature = "f16")]
631impl MaxDigits for bf16 {
632    #[inline(always)]
633    fn max_digits(_: u32) -> Option<usize> {
634        unimplemented!()
635    }
636}
637
638///// emin = -16382
639///// p2 = 113
640//#[cfg(feature = "f128")]
641//impl MaxDigits for f128 {
642//    #[inline(always)]
643//    fn max_digits(radix: u32) -> Option<usize> {
644//        match radix {
645//            6 => Some(10159),
646//            10 => Some(11565),
647//            12 => Some(11927),
648//            14 => Some(12194),
649//            18 => Some(12568),
650//            20 => Some(12706),
651//            22 => Some(12823),
652//            24 => Some(12924),
653//            26 => Some(13012),
654//            28 => Some(13089),
655//            30 => Some(13158),
656//            34 => Some(13277),
657//            36 => Some(13328),
658//            // Powers of two should be unreachable.
659//            // Odd numbers will have infinite digits.
660//            _ => None,
661//        }
662//    }
663//}
664
665// CONST FN
666// --------
667
668/// Get the maximum number of significant digits as a const fn.
669#[inline(always)]
670pub const fn f32_max_digits(radix: u32) -> Option<usize> {
671    match radix {
672        6 => Some(103),
673        10 => Some(114),
674        12 => Some(117),
675        14 => Some(119),
676        18 => Some(122),
677        20 => Some(123),
678        22 => Some(123),
679        24 => Some(124),
680        26 => Some(125),
681        28 => Some(125),
682        30 => Some(126),
683        34 => Some(127),
684        36 => Some(127),
685        // Powers of two should be unreachable.
686        // Odd numbers will have infinite digits.
687        _ => None,
688    }
689}
690
691/// Get the maximum number of significant digits as a const fn.
692#[inline(always)]
693pub const fn f64_max_digits(radix: u32) -> Option<usize> {
694    match radix {
695        6 => Some(682),
696        10 => Some(769),
697        12 => Some(792),
698        14 => Some(808),
699        18 => Some(832),
700        20 => Some(840),
701        22 => Some(848),
702        24 => Some(854),
703        26 => Some(859),
704        28 => Some(864),
705        30 => Some(868),
706        34 => Some(876),
707        36 => Some(879),
708        // Powers of two should be unreachable.
709        // Odd numbers will have infinite digits.
710        _ => None,
711    }
712}