Coverage Report

Created: 2026-01-13 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lexical-parse-float-1.0.6/src/limits.rs
Line
Count
Source
1
//! Determine the limits of exact exponent and mantissas for floats.
2
3
#![doc(hidden)]
4
5
use lexical_util::assert::debug_assert_radix;
6
#[cfg(feature = "f16")]
7
use lexical_util::bf16::bf16;
8
#[cfg(feature = "f16")]
9
use 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)]
37
pub 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
45
impl ExactFloat for f32 {
46
    #[inline(always)]
47
0
    fn exponent_limit(radix: u32) -> (i64, i64) {
48
0
        debug_assert_radix(radix);
49
0
        f32_exponent_limit(radix)
50
0
    }
51
52
    #[inline(always)]
53
0
    fn mantissa_limit(radix: u32) -> i64 {
54
0
        debug_assert_radix(radix);
55
0
        f32_mantissa_limit(radix)
56
0
    }
57
}
58
59
impl ExactFloat for f64 {
60
    #[inline(always)]
61
734
    fn exponent_limit(radix: u32) -> (i64, i64) {
62
734
        debug_assert_radix(radix);
63
734
        f64_exponent_limit(radix)
64
734
    }
65
66
    #[inline(always)]
67
281
    fn mantissa_limit(radix: u32) -> i64 {
68
281
        debug_assert_radix(radix);
69
281
        f64_mantissa_limit(radix)
70
281
    }
71
}
72
73
#[cfg(feature = "f16")]
74
impl 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")]
87
impl 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
//        f128_exponent_limit(radix)
105
//        }
106
//    }
107
//
108
//    #[inline(always)]
109
//    fn mantissa_limit(radix: u32) -> i64 {
110
//        debug_assert_radix(radix);
111
//        f128_mantissa_limit(radix)
112
//    }
113
//}
114
115
// CONST FN
116
// --------
117
118
/// Get the exponent limit as a const fn.
119
#[must_use]
120
#[inline(always)]
121
#[cfg(feature = "radix")]
122
pub const fn f32_exponent_limit(radix: u32) -> (i64, i64) {
123
    match radix {
124
        2 => (-127, 127),
125
        3 => (-15, 15),
126
        4 => (-63, 63),
127
        5 => (-10, 10),
128
        6 => (-15, 15),
129
        7 => (-8, 8),
130
        8 => (-42, 42),
131
        9 => (-7, 7),
132
        10 => (-10, 10),
133
        11 => (-6, 6),
134
        12 => (-15, 15),
135
        13 => (-6, 6),
136
        14 => (-8, 8),
137
        15 => (-6, 6),
138
        16 => (-31, 31),
139
        17 => (-5, 5),
140
        18 => (-7, 7),
141
        19 => (-5, 5),
142
        20 => (-10, 10),
143
        21 => (-5, 5),
144
        22 => (-6, 6),
145
        23 => (-5, 5),
146
        24 => (-15, 15),
147
        25 => (-5, 5),
148
        26 => (-6, 6),
149
        27 => (-5, 5),
150
        28 => (-8, 8),
151
        29 => (-4, 4),
152
        30 => (-6, 6),
153
        31 => (-4, 4),
154
        32 => (-25, 25),
155
        33 => (-4, 4),
156
        34 => (-5, 5),
157
        35 => (-4, 4),
158
        36 => (-7, 7),
159
        _ => (0, 0),
160
    }
161
}
162
163
/// Get the exponent limit as a const fn.
164
#[must_use]
165
#[inline(always)]
166
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
167
pub const fn f32_exponent_limit(radix: u32) -> (i64, i64) {
168
    match radix {
169
        2 => (-127, 127),
170
        4 => (-63, 63),
171
        8 => (-42, 42),
172
        10 => (-10, 10),
173
        16 => (-31, 31),
174
        32 => (-25, 25),
175
        _ => (0, 0),
176
    }
177
}
178
179
/// Get the exponent limit as a const fn.
180
#[must_use]
181
#[inline(always)]
182
#[cfg(not(feature = "power-of-two"))]
183
0
pub const fn f32_exponent_limit(radix: u32) -> (i64, i64) {
184
0
    match radix {
185
0
        10 => (-10, 10),
186
0
        _ => (0, 0),
187
    }
188
0
}
189
190
/// Get the mantissa limit as a const fn.
191
#[must_use]
192
#[inline(always)]
193
#[cfg(feature = "radix")]
194
pub const fn f32_mantissa_limit(radix: u32) -> i64 {
195
    match radix {
196
        2 => 24,
197
        3 => 15,
198
        4 => 12,
199
        5 => 10,
200
        6 => 9,
201
        7 => 8,
202
        8 => 8,
203
        9 => 7,
204
        10 => 7,
205
        11 => 6,
206
        12 => 6,
207
        13 => 6,
208
        14 => 6,
209
        15 => 6,
210
        16 => 6,
211
        17 => 5,
212
        18 => 5,
213
        19 => 5,
214
        20 => 5,
215
        21 => 5,
216
        22 => 5,
217
        23 => 5,
218
        24 => 5,
219
        25 => 5,
220
        26 => 5,
221
        27 => 5,
222
        28 => 4,
223
        29 => 4,
224
        30 => 4,
225
        31 => 4,
226
        32 => 4,
227
        33 => 4,
228
        34 => 4,
229
        35 => 4,
230
        36 => 4,
231
        _ => 0,
232
    }
233
}
234
235
/// Get the mantissa limit as a const fn.
236
#[must_use]
237
#[inline(always)]
238
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
239
pub const fn f32_mantissa_limit(radix: u32) -> i64 {
240
    match radix {
241
        2 => 24,
242
        4 => 12,
243
        8 => 8,
244
        10 => 7,
245
        16 => 6,
246
        32 => 4,
247
        _ => 0,
248
    }
249
}
250
251
/// Get the mantissa limit as a const fn.
252
#[must_use]
253
#[inline(always)]
254
#[cfg(not(feature = "power-of-two"))]
255
0
pub const fn f32_mantissa_limit(radix: u32) -> i64 {
256
0
    match radix {
257
0
        10 => 7,
258
0
        _ => 0,
259
    }
260
0
}
261
262
/// Get the exponent limit as a const fn.
263
#[must_use]
264
#[inline(always)]
265
#[cfg(feature = "radix")]
266
pub const fn f64_exponent_limit(radix: u32) -> (i64, i64) {
267
    match radix {
268
        2 => (-1023, 1023),
269
        3 => (-33, 33),
270
        4 => (-511, 511),
271
        5 => (-22, 22),
272
        6 => (-33, 33),
273
        7 => (-18, 18),
274
        8 => (-341, 341),
275
        9 => (-16, 16),
276
        10 => (-22, 22),
277
        11 => (-15, 15),
278
        12 => (-33, 33),
279
        13 => (-14, 14),
280
        14 => (-18, 18),
281
        15 => (-13, 13),
282
        16 => (-255, 255),
283
        17 => (-12, 12),
284
        18 => (-16, 16),
285
        19 => (-12, 12),
286
        20 => (-22, 22),
287
        21 => (-12, 12),
288
        22 => (-15, 15),
289
        23 => (-11, 11),
290
        24 => (-33, 33),
291
        25 => (-11, 11),
292
        26 => (-14, 14),
293
        27 => (-11, 11),
294
        28 => (-18, 18),
295
        29 => (-10, 10),
296
        30 => (-13, 13),
297
        31 => (-10, 10),
298
        32 => (-204, 204),
299
        33 => (-10, 10),
300
        34 => (-12, 12),
301
        35 => (-10, 10),
302
        36 => (-16, 16),
303
        _ => (0, 0),
304
    }
305
}
306
307
// Get the exponent limit as a const fn.
308
#[must_use]
309
#[inline(always)]
310
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
311
pub const fn f64_exponent_limit(radix: u32) -> (i64, i64) {
312
    match radix {
313
        2 => (-1023, 1023),
314
        4 => (-511, 511),
315
        8 => (-341, 341),
316
        10 => (-22, 22),
317
        16 => (-255, 255),
318
        32 => (-204, 204),
319
        _ => (0, 0),
320
    }
321
}
322
323
/// Get the exponent limit as a const fn.
324
#[must_use]
325
#[inline(always)]
326
#[cfg(not(feature = "power-of-two"))]
327
734
pub const fn f64_exponent_limit(radix: u32) -> (i64, i64) {
328
734
    match radix {
329
734
        10 => (-22, 22),
330
0
        _ => (0, 0),
331
    }
332
734
}
333
334
/// Get the mantissa limit as a const fn.
335
#[must_use]
336
#[inline(always)]
337
#[cfg(feature = "radix")]
338
pub const fn f64_mantissa_limit(radix: u32) -> i64 {
339
    match radix {
340
        2 => 53,
341
        3 => 33,
342
        4 => 26,
343
        5 => 22,
344
        6 => 20,
345
        7 => 18,
346
        8 => 17,
347
        9 => 16,
348
        10 => 15,
349
        11 => 15,
350
        12 => 14,
351
        13 => 14,
352
        14 => 13,
353
        15 => 13,
354
        16 => 13,
355
        17 => 12,
356
        18 => 12,
357
        19 => 12,
358
        20 => 12,
359
        21 => 12,
360
        22 => 11,
361
        23 => 11,
362
        24 => 11,
363
        25 => 11,
364
        26 => 11,
365
        27 => 11,
366
        28 => 11,
367
        29 => 10,
368
        30 => 10,
369
        31 => 10,
370
        32 => 10,
371
        33 => 10,
372
        34 => 10,
373
        35 => 10,
374
        36 => 10,
375
        _ => 0,
376
    }
377
}
378
379
/// Get the mantissa limit as a const fn.
380
#[must_use]
381
#[inline(always)]
382
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
383
pub const fn f64_mantissa_limit(radix: u32) -> i64 {
384
    match radix {
385
        2 => 53,
386
        4 => 26,
387
        8 => 17,
388
        10 => 15,
389
        16 => 13,
390
        32 => 10,
391
        _ => 0,
392
    }
393
}
394
395
/// Get the mantissa limit as a const fn.
396
#[must_use]
397
#[inline(always)]
398
#[cfg(not(feature = "power-of-two"))]
399
281
pub const fn f64_mantissa_limit(radix: u32) -> i64 {
400
281
    match radix {
401
281
        10 => 15,
402
0
        _ => 0,
403
    }
404
281
}
405
406
/// Get the exponent limit as a const fn.
407
#[must_use]
408
#[inline(always)]
409
#[cfg(feature = "f128")]
410
#[cfg(feature = "radix")]
411
pub const fn f128_exponent_limit(radix: u32) -> (i64, i64) {
412
    match radix {
413
        2 => (-16494, 16383),
414
        3 => (-71, 71),
415
        4 => (-8247, 8191),
416
        5 => (-48, 48),
417
        6 => (-71, 71),
418
        7 => (-40, 40),
419
        8 => (-5498, 5461),
420
        9 => (-35, 35),
421
        10 => (-48, 48),
422
        11 => (-32, 32),
423
        12 => (-71, 71),
424
        13 => (-30, 30),
425
        14 => (-40, 40),
426
        15 => (-28, 28),
427
        16 => (-4123, 4095),
428
        17 => (-27, 27),
429
        18 => (-35, 35),
430
        19 => (-26, 26),
431
        20 => (-48, 48),
432
        21 => (-25, 25),
433
        22 => (-32, 32),
434
        23 => (-24, 24),
435
        24 => (-71, 71),
436
        25 => (-24, 24),
437
        26 => (-30, 30),
438
        27 => (-23, 23),
439
        28 => (-40, 40),
440
        29 => (-23, 23),
441
        30 => (-28, 28),
442
        31 => (-22, 22),
443
        32 => (-3298, 3276),
444
        33 => (-22, 22),
445
        34 => (-27, 27),
446
        35 => (-22, 22),
447
        36 => (-35, 35),
448
        // Invalid radix
449
        _ => (0, 0),
450
    }
451
}
452
453
/// Get the exponent limit as a const fn.
454
#[inline(always)]
455
#[cfg(feature = "f128")]
456
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
457
pub const fn f128_exponent_limit(radix: u32) -> (i64, i64) {
458
    match radix {
459
        2 => (-16494, 16383),
460
        4 => (-8247, 8191),
461
        8 => (-5498, 5461),
462
        10 => (-48, 48),
463
        16 => (-4123, 4095),
464
        32 => (-3298, 3276),
465
        // Invalid radix
466
        _ => (0, 0),
467
    }
468
}
469
470
/// Get the exponent limit as a const fn.
471
#[must_use]
472
#[inline(always)]
473
#[cfg(feature = "f128")]
474
#[cfg(not(feature = "power-of-two"))]
475
pub const fn f128_exponent_limit(radix: u32) -> (i64, i64) {
476
    match radix {
477
        10 => (-48, 48),
478
        // Invalid radix
479
        _ => (0, 0),
480
    }
481
}
482
483
/// Get the mantissa limit as a const fn.
484
#[must_use]
485
#[inline(always)]
486
#[cfg(feature = "f128")]
487
#[cfg(feature = "radix")]
488
pub const fn f128_mantissa_limit(radix: u32) -> i64 {
489
    match radix {
490
        2 => 113,
491
        3 => 71,
492
        4 => 56,
493
        5 => 48,
494
        6 => 43,
495
        7 => 40,
496
        8 => 37,
497
        9 => 35,
498
        10 => 34,
499
        11 => 32,
500
        12 => 31,
501
        13 => 30,
502
        14 => 29,
503
        15 => 28,
504
        16 => 28,
505
        17 => 27,
506
        18 => 27,
507
        19 => 26,
508
        20 => 26,
509
        21 => 25,
510
        22 => 25,
511
        23 => 24,
512
        24 => 24,
513
        25 => 24,
514
        26 => 24,
515
        27 => 23,
516
        28 => 23,
517
        29 => 23,
518
        30 => 23,
519
        31 => 22,
520
        32 => 22,
521
        33 => 22,
522
        34 => 22,
523
        35 => 22,
524
        36 => 21,
525
        // Invalid radix
526
        _ => 0,
527
    }
528
}
529
530
/// Get the mantissa limit as a const fn.
531
#[must_use]
532
#[inline(always)]
533
#[cfg(feature = "f128")]
534
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
535
pub const fn f128_mantissa_limit(radix: u32) -> i64 {
536
    match radix {
537
        2 => 113,
538
        4 => 56,
539
        8 => 37,
540
        10 => 34,
541
        16 => 28,
542
        32 => 22,
543
        // Invalid radix
544
        _ => 0,
545
    }
546
}
547
548
/// Get the mantissa limit as a const fn.
549
#[must_use]
550
#[inline(always)]
551
#[cfg(feature = "f128")]
552
#[cfg(not(feature = "power-of-two"))]
553
pub const fn f128_mantissa_limit(radix: u32) -> i64 {
554
    match radix {
555
        10 => 34,
556
        // Invalid radix
557
        _ => 0,
558
    }
559
}
560
561
// POWER LIMITS
562
// ------------
563
564
//  The code used to generate these limits is as follows:
565
//
566
//  ```text
567
//  import math
568
//
569
//  def find_power(base, max_value):
570
//      '''Using log is unreliable, since it uses float math.'''
571
//
572
//      power = 0
573
//      while base**power < max_value:
574
//          power += 1
575
//      return power - 1
576
//
577
//  def print_function(bits):
578
//      print('#[inline(always)]')
579
//      print(f'pub const fn u{bits}_power_limit(radix: u32) -> u32 {{')
580
//      print('    match radix {')
581
//      max_value = 2**bits - 1
582
//      for radix in range(2, 37):
583
//          power = find_power(radix, max_value)
584
//          print(f'        {radix} => {power},')
585
//      print('        // Any other radix should be unreachable.')
586
//      print('        _ => 1,')
587
//      print('    }')
588
//      print('}')
589
//      print('')
590
//
591
//  print_function(32)
592
//  print_function(64)
593
//  ```
594
595
/// Get the maximum value for `radix^N` that can be represented in a u32.
596
/// This is calculated as `⌊log(2^32 - 1, b)⌋`.
597
#[must_use]
598
#[inline(always)]
599
#[cfg(feature = "radix")]
600
pub const fn u32_power_limit(radix: u32) -> u32 {
601
    match radix {
602
        2 => 31,
603
        3 => 20,
604
        4 => 15,
605
        5 => 13,
606
        6 => 12,
607
        7 => 11,
608
        8 => 10,
609
        9 => 10,
610
        10 => 9,
611
        11 => 9,
612
        12 => 8,
613
        13 => 8,
614
        14 => 8,
615
        15 => 8,
616
        16 => 7,
617
        17 => 7,
618
        18 => 7,
619
        19 => 7,
620
        20 => 7,
621
        21 => 7,
622
        22 => 7,
623
        23 => 7,
624
        24 => 6,
625
        25 => 6,
626
        26 => 6,
627
        27 => 6,
628
        28 => 6,
629
        29 => 6,
630
        30 => 6,
631
        31 => 6,
632
        32 => 6,
633
        33 => 6,
634
        34 => 6,
635
        35 => 6,
636
        36 => 6,
637
        // Any other radix should be unreachable.
638
        _ => 1,
639
    }
640
}
641
642
/// This is calculated as `⌊log(2^32 - 1, b)⌋`.
643
#[must_use]
644
#[inline(always)]
645
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
646
pub const fn u32_power_limit(radix: u32) -> u32 {
647
    match radix {
648
        2 => 31,
649
        4 => 15,
650
        5 => 13,
651
        8 => 10,
652
        10 => 9,
653
        16 => 7,
654
        32 => 6,
655
        // Any other radix should be unreachable.
656
        _ => 1,
657
    }
658
}
659
660
/// This is calculated as `⌊log(2^32 - 1, b)⌋`.
661
#[must_use]
662
#[inline(always)]
663
#[cfg(not(feature = "power-of-two"))]
664
0
pub const fn u32_power_limit(radix: u32) -> u32 {
665
0
    match radix {
666
0
        5 => 13,
667
0
        10 => 9,
668
        // Any other radix should be unreachable.
669
0
        _ => 1,
670
    }
671
0
}
672
673
/// Get the maximum value for `radix^N` that can be represented in a u64.
674
/// This is calculated as `⌊log(2^64 - 1, b)⌋`.
675
#[must_use]
676
#[inline(always)]
677
#[cfg(feature = "radix")]
678
pub const fn u64_power_limit(radix: u32) -> u32 {
679
    match radix {
680
        2 => 63,
681
        3 => 40,
682
        4 => 31,
683
        5 => 27,
684
        6 => 24,
685
        7 => 22,
686
        8 => 21,
687
        9 => 20,
688
        10 => 19,
689
        11 => 18,
690
        12 => 17,
691
        13 => 17,
692
        14 => 16,
693
        15 => 16,
694
        16 => 15,
695
        17 => 15,
696
        18 => 15,
697
        19 => 15,
698
        20 => 14,
699
        21 => 14,
700
        22 => 14,
701
        23 => 14,
702
        24 => 13,
703
        25 => 13,
704
        26 => 13,
705
        27 => 13,
706
        28 => 13,
707
        29 => 13,
708
        30 => 13,
709
        31 => 12,
710
        32 => 12,
711
        33 => 12,
712
        34 => 12,
713
        35 => 12,
714
        36 => 12,
715
        // Any other radix should be unreachable.
716
        _ => 1,
717
    }
718
}
719
720
/// Get the maximum value for `radix^N` that can be represented in a u64.
721
/// This is calculated as `⌊log(2^64 - 1, b)⌋`.
722
#[must_use]
723
#[inline(always)]
724
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
725
pub const fn u64_power_limit(radix: u32) -> u32 {
726
    match radix {
727
        2 => 63,
728
        4 => 31,
729
        5 => 27,
730
        8 => 21,
731
        10 => 19,
732
        16 => 15,
733
        32 => 12,
734
        // Any other radix should be unreachable.
735
        _ => 1,
736
    }
737
}
738
739
#[must_use]
740
#[inline(always)]
741
#[cfg(not(feature = "power-of-two"))]
742
28
pub const fn u64_power_limit(radix: u32) -> u32 {
743
28
    match radix {
744
14
        5 => 27,
745
14
        10 => 19,
746
        // Any other radix should be unreachable.
747
0
        _ => 1,
748
    }
749
28
}
750
751
// MAX DIGITS
752
// ----------
753
754
/// Calculate the maximum number of digits possible in the mantissa.
755
///
756
/// Returns the maximum number of digits plus one.
757
///
758
/// We can exactly represent a float in radix `b` from radix 2 if
759
/// `b` is divisible by 2. This function calculates the exact number of
760
/// digits required to exactly represent that float. This makes sense,
761
/// and the exact reference and I quote is:
762
///
763
///  > A necessary and sufficient condition for all numbers representable in
764
///  > radix β
765
///  > with a finite number of digits to be representable in radix γ with a
766
///  > finite number of digits is that β should divide an integer power of γ.
767
///
768
/// According to the "Handbook of Floating Point Arithmetic",
769
/// for IEEE754, with `emin` being the min exponent, `p2` being the
770
/// precision, and `b` being the radix, the number of digits follows as:
771
///
772
/// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
773
///
774
/// For f16, this follows as:
775
///     emin = -14
776
///     p2 = 11
777
///
778
/// For bfloat16 , this follows as:
779
///     emin = -126
780
///     p2 = 8
781
///
782
/// For f32, this follows as:
783
///     emin = -126
784
///     p2 = 24
785
///
786
/// For f64, this follows as:
787
///     emin = -1022
788
///     p2 = 53
789
///
790
/// For f128, this follows as:
791
///     emin = -16382
792
///     p2 = 113
793
///
794
/// In Python:
795
///     `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2),
796
/// b))`
797
///
798
/// This was used to calculate the maximum number of digits for [2, 36].
799
///
800
/// The minimum, denormal exponent can be calculated as follows: given
801
/// the number of exponent bits `exp_bits`, and the number of bits
802
/// in the mantissa `mantissa_bits`, we have an exponent bias
803
/// `exp_bias` equal to `2^(exp_bits-1) - 1 + mantissa_bits`. We
804
/// therefore have a denormal exponent `denormal_exp` equal to
805
/// `1 - exp_bias` and the minimum, denormal float `min_float` is
806
/// therefore `2^denormal_exp`.
807
///
808
/// For f16, this follows as:
809
///     exp_bits = 5
810
///     mantissa_bits = 10
811
///     exp_bias = 25
812
///     denormal_exp = -24
813
///     min_float = 5.96 * 10^−8
814
///
815
/// For bfloat16, this follows as:
816
///     exp_bits = 8
817
///     mantissa_bits = 7
818
///     exp_bias = 134
819
///     denormal_exp = -133
820
///     min_float = 9.18 * 10^−41
821
///
822
/// For f32, this follows as:
823
///     exp_bits = 8
824
///     mantissa_bits = 23
825
///     exp_bias = 150
826
///     denormal_exp = -149
827
///     min_float = 1.40 * 10^−45
828
///
829
/// For f64, this follows as:
830
///     exp_bits = 11
831
///     mantissa_bits = 52
832
///     exp_bias = 1075
833
///     denormal_exp = -1074
834
///     min_float = 5.00 * 10^−324
835
///
836
/// For f128, this follows as:
837
///     exp_bits = 15
838
///     mantissa_bits = 112
839
///     exp_bias = 16495
840
///     denormal_exp = -16494
841
///     min_float = 6.48 * 10^−4966
842
///
843
/// These match statements can be generated with the following Python
844
/// code:
845
/// ```python
846
/// import math
847
///
848
/// def digits(emin, p2, b):
849
///     return -emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))
850
///
851
/// def max_digits(emin, p2):
852
///     radices = [6, 10, 12, 14, 18, 20, 22, 24 26 28, 30, 34, 36]
853
///     print('match radix {')
854
///     for radix in radices:
855
///         value = digits(emin, p2, radix)
856
///         print(f'    {radix} => Some({value + 2}),')
857
///     print('    // Powers of two should be unreachable.')
858
///     print('    // Odd numbers will have infinite digits.')
859
///     print('    _ => None,')
860
///     print('}')
861
/// ```
862
#[allow(clippy::doc_markdown)] // reason="not meant to be function parameters"
863
pub trait MaxDigits {
864
    fn max_digits(radix: u32) -> Option<usize>;
865
}
866
867
/// emin = -126
868
/// p2 = 24
869
impl MaxDigits for f32 {
870
    #[inline(always)]
871
0
    fn max_digits(radix: u32) -> Option<usize> {
872
0
        debug_assert_radix(radix);
873
0
        f32_max_digits(radix)
874
0
    }
875
}
876
877
/// emin = -1022
878
/// p2 = 53
879
impl MaxDigits for f64 {
880
    #[inline(always)]
881
14
    fn max_digits(radix: u32) -> Option<usize> {
882
14
        debug_assert_radix(radix);
883
14
        f64_max_digits(radix)
884
14
    }
885
}
886
887
#[cfg(feature = "f16")]
888
impl MaxDigits for f16 {
889
    #[inline(always)]
890
    fn max_digits(_: u32) -> Option<usize> {
891
        unimplemented!()
892
    }
893
}
894
895
#[cfg(feature = "f16")]
896
impl MaxDigits for bf16 {
897
    #[inline(always)]
898
    fn max_digits(_: u32) -> Option<usize> {
899
        unimplemented!()
900
    }
901
}
902
903
///// `emin = -16382`
904
///// `p2 = 113`
905
//#[cfg(feature = "f128")]
906
//impl MaxDigits for f128 {
907
//    #[inline(always)]
908
//    fn max_digits(radix: u32) -> Option<usize> {
909
//        match radix {
910
//            6 => Some(10159),
911
//            10 => Some(11565),
912
//            12 => Some(11927),
913
//            14 => Some(12194),
914
//            18 => Some(12568),
915
//            20 => Some(12706),
916
//            22 => Some(12823),
917
//            24 => Some(12924),
918
//            26 => Some(13012),
919
//            28 => Some(13089),
920
//            30 => Some(13158),
921
//            34 => Some(13277),
922
//            36 => Some(13328),
923
//            // Powers of two should be unreachable.
924
//            // Odd numbers will have infinite digits.
925
//            _ => None,
926
//        }
927
//    }
928
//}
929
930
// CONST FN
931
// --------
932
933
/// Get the maximum number of significant digits as a const fn.
934
#[must_use]
935
#[inline(always)]
936
0
pub const fn f32_max_digits(radix: u32) -> Option<usize> {
937
0
    match radix {
938
0
        6 => Some(103),
939
0
        10 => Some(114),
940
0
        12 => Some(117),
941
0
        14 => Some(119),
942
0
        18 => Some(122),
943
0
        20 => Some(123),
944
0
        22 => Some(123),
945
0
        24 => Some(124),
946
0
        26 => Some(125),
947
0
        28 => Some(125),
948
0
        30 => Some(126),
949
0
        34 => Some(127),
950
0
        36 => Some(127),
951
        // Powers of two should be unreachable.
952
        // Odd numbers will have infinite digits.
953
0
        _ => None,
954
    }
955
0
}
956
957
/// Get the maximum number of significant digits as a const fn.
958
#[must_use]
959
#[inline(always)]
960
14
pub const fn f64_max_digits(radix: u32) -> Option<usize> {
961
14
    match radix {
962
0
        6 => Some(682),
963
14
        10 => Some(769),
964
0
        12 => Some(792),
965
0
        14 => Some(808),
966
0
        18 => Some(832),
967
0
        20 => Some(840),
968
0
        22 => Some(848),
969
0
        24 => Some(854),
970
0
        26 => Some(859),
971
0
        28 => Some(864),
972
0
        30 => Some(868),
973
0
        34 => Some(876),
974
0
        36 => Some(879),
975
        // Powers of two should be unreachable.
976
        // Odd numbers will have infinite digits.
977
0
        _ => None,
978
    }
979
14
}