xref: /freebsd/contrib/llvm-project/libcxx/src/include/to_chars_floating_point.h (revision a03411e84728e9b267056fd31c7d1d9d1dc1b01e)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Copyright (c) Microsoft Corporation.
10 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 
12 // This implementation is dedicated to the memory of Mary and Thavatchai.
13 
14 #ifndef _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
15 #define _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
16 
17 // Avoid formatting to keep the changes with the original code minimal.
18 // clang-format off
19 
20 #include <__algorithm/find.h>
21 #include <__algorithm/find_if.h>
22 #include <__algorithm/lower_bound.h>
23 #include <__algorithm/min.h>
24 #include <__assert>
25 #include <__config>
26 #include <__functional/operations.h>
27 #include <__iterator/access.h>
28 #include <__iterator/size.h>
29 #include <bit>
30 #include <cfloat>
31 #include <climits>
32 
33 #include "include/ryu/ryu.h"
34 
35 _LIBCPP_BEGIN_NAMESPACE_STD
36 
37 namespace __itoa {
38 inline constexpr char _Charconv_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
39     'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
40 static_assert(_VSTD::size(_Charconv_digits) == 36);
41 } // __itoa
42 
43 // vvvvvvvvvv DERIVED FROM corecrt_internal_fltintrn.h vvvvvvvvvv
44 
45 template <class _FloatingType>
46 struct _Floating_type_traits;
47 
48 template <>
49 struct _Floating_type_traits<float> {
50     static constexpr int32_t _Mantissa_bits = FLT_MANT_DIG;
51     static constexpr int32_t _Exponent_bits = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
52 
53     static constexpr int32_t _Maximum_binary_exponent = FLT_MAX_EXP - 1;
54     static constexpr int32_t _Minimum_binary_exponent = FLT_MIN_EXP - 1;
55 
56     static constexpr int32_t _Exponent_bias = 127;
57 
58     static constexpr int32_t _Sign_shift     = _Exponent_bits + _Mantissa_bits - 1;
59     static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1;
60 
61     using _Uint_type = uint32_t;
62 
63     static constexpr uint32_t _Exponent_mask             = (1u << _Exponent_bits) - 1;
64     static constexpr uint32_t _Normal_mantissa_mask      = (1u << _Mantissa_bits) - 1;
65     static constexpr uint32_t _Denormal_mantissa_mask    = (1u << (_Mantissa_bits - 1)) - 1;
66     static constexpr uint32_t _Special_nan_mantissa_mask = 1u << (_Mantissa_bits - 2);
67     static constexpr uint32_t _Shifted_sign_mask         = 1u << _Sign_shift;
68     static constexpr uint32_t _Shifted_exponent_mask     = _Exponent_mask << _Exponent_shift;
69 };
70 
71 template <>
72 struct _Floating_type_traits<double> {
73     static constexpr int32_t _Mantissa_bits = DBL_MANT_DIG;
74     static constexpr int32_t _Exponent_bits = sizeof(double) * CHAR_BIT - DBL_MANT_DIG;
75 
76     static constexpr int32_t _Maximum_binary_exponent = DBL_MAX_EXP - 1;
77     static constexpr int32_t _Minimum_binary_exponent = DBL_MIN_EXP - 1;
78 
79     static constexpr int32_t _Exponent_bias = 1023;
80 
81     static constexpr int32_t _Sign_shift     = _Exponent_bits + _Mantissa_bits - 1;
82     static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1;
83 
84     using _Uint_type = uint64_t;
85 
86     static constexpr uint64_t _Exponent_mask             = (1ULL << _Exponent_bits) - 1;
87     static constexpr uint64_t _Normal_mantissa_mask      = (1ULL << _Mantissa_bits) - 1;
88     static constexpr uint64_t _Denormal_mantissa_mask    = (1ULL << (_Mantissa_bits - 1)) - 1;
89     static constexpr uint64_t _Special_nan_mantissa_mask = 1ULL << (_Mantissa_bits - 2);
90     static constexpr uint64_t _Shifted_sign_mask         = 1ULL << _Sign_shift;
91     static constexpr uint64_t _Shifted_exponent_mask     = _Exponent_mask << _Exponent_shift;
92 };
93 
94 // ^^^^^^^^^^ DERIVED FROM corecrt_internal_fltintrn.h ^^^^^^^^^^
95 
96 // FUNCTION to_chars (FLOATING-POINT TO STRING)
97 template <class _Floating>
98 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
99 to_chars_result _Floating_to_chars_hex_precision(
100     char* _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
101 
102     // * Determine the effective _Precision.
103     // * Later, we'll decrement _Precision when printing each hexit after the decimal point.
104 
105     // The hexits after the decimal point correspond to the explicitly stored fraction bits.
106     // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, which is 6 hexits.
107     // double explicitly stores 52 fraction bits. 52 / 4 == 13, which is 13 hexits.
108     constexpr int _Full_precision         = _IsSame<_Floating, float>::value ? 6 : 13;
109     constexpr int _Adjusted_explicit_bits = _Full_precision * 4;
110 
111     if (_Precision < 0) {
112         // C11 7.21.6.1 "The fprintf function"/5: "A negative precision argument is taken as if the precision were
113         // omitted." /8: "if the precision is missing and FLT_RADIX is a power of 2, then the precision is sufficient
114         // for an exact representation of the value"
115         _Precision = _Full_precision;
116     }
117 
118     // * Extract the _Ieee_mantissa and _Ieee_exponent.
119     using _Traits    = _Floating_type_traits<_Floating>;
120     using _Uint_type = typename _Traits::_Uint_type;
121 
122     const _Uint_type _Uint_value    = _VSTD::bit_cast<_Uint_type>(_Value);
123     const _Uint_type _Ieee_mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
124     const int32_t _Ieee_exponent    = static_cast<int32_t>(_Uint_value >> _Traits::_Exponent_shift);
125 
126     // * Prepare the _Adjusted_mantissa. This is aligned to hexit boundaries,
127     // * with the implicit bit restored (0 for zero values and subnormal values, 1 for normal values).
128     // * Also calculate the _Unbiased_exponent. This unifies the processing of zero, subnormal, and normal values.
129     _Uint_type _Adjusted_mantissa;
130 
131     if constexpr (_IsSame<_Floating, float>::value) {
132         _Adjusted_mantissa = _Ieee_mantissa << 1; // align to hexit boundary (23 isn't divisible by 4)
133     } else {
134         _Adjusted_mantissa = _Ieee_mantissa; // already aligned (52 is divisible by 4)
135     }
136 
137     int32_t _Unbiased_exponent;
138 
139     if (_Ieee_exponent == 0) { // zero or subnormal
140         // implicit bit is 0
141 
142         if (_Ieee_mantissa == 0) { // zero
143             // C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
144             _Unbiased_exponent = 0;
145         } else { // subnormal
146             _Unbiased_exponent = 1 - _Traits::_Exponent_bias;
147         }
148     } else { // normal
149         _Adjusted_mantissa |= _Uint_type{1} << _Adjusted_explicit_bits; // implicit bit is 1
150         _Unbiased_exponent = _Ieee_exponent - _Traits::_Exponent_bias;
151     }
152 
153     // _Unbiased_exponent is within [-126, 127] for float, [-1022, 1023] for double.
154 
155     // * Decompose _Unbiased_exponent into _Sign_character and _Absolute_exponent.
156     char _Sign_character;
157     uint32_t _Absolute_exponent;
158 
159     if (_Unbiased_exponent < 0) {
160         _Sign_character    = '-';
161         _Absolute_exponent = static_cast<uint32_t>(-_Unbiased_exponent);
162     } else {
163         _Sign_character    = '+';
164         _Absolute_exponent = static_cast<uint32_t>(_Unbiased_exponent);
165     }
166 
167     // _Absolute_exponent is within [0, 127] for float, [0, 1023] for double.
168 
169     // * Perform a single bounds check.
170     {
171         int32_t _Exponent_length;
172 
173         if (_Absolute_exponent < 10) {
174             _Exponent_length = 1;
175         } else if (_Absolute_exponent < 100) {
176             _Exponent_length = 2;
177         } else if constexpr (_IsSame<_Floating, float>::value) {
178             _Exponent_length = 3;
179         } else if (_Absolute_exponent < 1000) {
180             _Exponent_length = 3;
181         } else {
182             _Exponent_length = 4;
183         }
184 
185         // _Precision might be enormous; avoid integer overflow by testing it separately.
186         ptrdiff_t _Buffer_size = _Last - _First;
187 
188         if (_Buffer_size < _Precision) {
189             return {_Last, errc::value_too_large};
190         }
191 
192         _Buffer_size -= _Precision;
193 
194         const int32_t _Length_excluding_precision = 1 // leading hexit
195                                                     + static_cast<int32_t>(_Precision > 0) // possible decimal point
196                                                     // excluding `+ _Precision`, hexits after decimal point
197                                                     + 2 // "p+" or "p-"
198                                                     + _Exponent_length; // exponent
199 
200         if (_Buffer_size < _Length_excluding_precision) {
201             return {_Last, errc::value_too_large};
202         }
203     }
204 
205     // * Perform rounding when we've been asked to omit hexits.
206     if (_Precision < _Full_precision) {
207         // _Precision is within [0, 5] for float, [0, 12] for double.
208 
209         // _Dropped_bits is within [4, 24] for float, [4, 52] for double.
210         const int _Dropped_bits = (_Full_precision - _Precision) * 4;
211 
212         // Perform rounding by adding an appropriately-shifted bit.
213 
214         // This can propagate carries all the way into the leading hexit. Examples:
215         // "0.ff9" rounded to a precision of 2 is "1.00".
216         // "1.ff9" rounded to a precision of 2 is "2.00".
217 
218         // Note that the leading hexit participates in the rounding decision. Examples:
219         // "0.8" rounded to a precision of 0 is "0".
220         // "1.8" rounded to a precision of 0 is "2".
221 
222         // Reference implementation with suboptimal codegen:
223         // bool _Should_round_up(bool _Lsb_bit, bool _Round_bit, bool _Has_tail_bits) {
224         //    // If there are no insignificant set bits, the value is exactly-representable and should not be rounded.
225         //    //
226         //    // If there are insignificant set bits, we need to round according to round_to_nearest.
227         //    // We need to handle two cases: we round up if either [1] the value is slightly greater
228         //    // than the midpoint between two exactly-representable values or [2] the value is exactly the midpoint
229         //    // between two exactly-representable values and the greater of the two is even (this is "round-to-even").
230         //    return _Round_bit && (_Has_tail_bits || _Lsb_bit);
231         //}
232         // const bool _Lsb_bit       = (_Adjusted_mantissa & (_Uint_type{1} << _Dropped_bits)) != 0;
233         // const bool _Round_bit     = (_Adjusted_mantissa & (_Uint_type{1} << (_Dropped_bits - 1))) != 0;
234         // const bool _Has_tail_bits = (_Adjusted_mantissa & ((_Uint_type{1} << (_Dropped_bits - 1)) - 1)) != 0;
235         // const bool _Should_round = _Should_round_up(_Lsb_bit, _Round_bit, _Has_tail_bits);
236         // _Adjusted_mantissa += _Uint_type{_Should_round} << _Dropped_bits;
237 
238         // Example for optimized implementation: Let _Dropped_bits be 8.
239         //          Bit index: ...[8]76543210
240         // _Adjusted_mantissa: ...[L]RTTTTTTT (not depicting known details, like hexit alignment)
241         // By focusing on the bit at index _Dropped_bits, we can avoid unnecessary branching and shifting.
242 
243         // Bit index: ...[8]76543210
244         //  _Lsb_bit: ...[L]RTTTTTTT
245         const _Uint_type _Lsb_bit = _Adjusted_mantissa;
246 
247         //  Bit index: ...9[8]76543210
248         // _Round_bit: ...L[R]TTTTTTT0
249         const _Uint_type _Round_bit = _Adjusted_mantissa << 1;
250 
251         // We can detect (without branching) whether any of the trailing bits are set.
252         // Due to _Should_round below, this computation will be used if and only if R is 1, so we can assume that here.
253         //      Bit index: ...9[8]76543210
254         //     _Round_bit: ...L[1]TTTTTTT0
255         // _Has_tail_bits: ....[H]........
256 
257         // If all of the trailing bits T are 0, then `_Round_bit - 1` will produce 0 for H (due to R being 1).
258         // If any of the trailing bits T are 1, then `_Round_bit - 1` will produce 1 for H (due to R being 1).
259         const _Uint_type _Has_tail_bits = _Round_bit - 1;
260 
261         // Finally, we can use _Should_round_up() logic with bitwise-AND and bitwise-OR,
262         // selecting just the bit at index _Dropped_bits. This is the appropriately-shifted bit that we want.
263         const _Uint_type _Should_round = _Round_bit & (_Has_tail_bits | _Lsb_bit) & (_Uint_type{1} << _Dropped_bits);
264 
265         // This rounding technique is dedicated to the memory of Peppermint. =^..^=
266         _Adjusted_mantissa += _Should_round;
267     }
268 
269     // * Print the leading hexit, then mask it away.
270     {
271         const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Adjusted_explicit_bits);
272         _LIBCPP_ASSERT_UNCATEGORIZED(_Nibble < 3, "");
273         const char _Leading_hexit = static_cast<char>('0' + _Nibble);
274 
275         *_First++ = _Leading_hexit;
276 
277         constexpr _Uint_type _Mask = (_Uint_type{1} << _Adjusted_explicit_bits) - 1;
278         _Adjusted_mantissa &= _Mask;
279     }
280 
281     // * Print the decimal point and trailing hexits.
282 
283     // C11 7.21.6.1 "The fprintf function"/8:
284     // "if the precision is zero and the # flag is not specified, no decimal-point character appears."
285     if (_Precision > 0) {
286         *_First++ = '.';
287 
288         int32_t _Number_of_bits_remaining = _Adjusted_explicit_bits; // 24 for float, 52 for double
289 
290         for (;;) {
291             _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining >= 4, "");
292             _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining % 4 == 0, "");
293             _Number_of_bits_remaining -= 4;
294 
295             const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining);
296             _LIBCPP_ASSERT_UNCATEGORIZED(_Nibble < 16, "");
297             const char _Hexit = __itoa::_Charconv_digits[_Nibble];
298 
299             *_First++ = _Hexit;
300 
301             // _Precision is the number of hexits that still need to be printed.
302             --_Precision;
303             if (_Precision == 0) {
304                 break; // We're completely done with this phase.
305             }
306             // Otherwise, we need to keep printing hexits.
307 
308             if (_Number_of_bits_remaining == 0) {
309                 // We've finished printing _Adjusted_mantissa, so all remaining hexits are '0'.
310                 _VSTD::memset(_First, '0', static_cast<size_t>(_Precision));
311                 _First += _Precision;
312                 break;
313             }
314 
315             // Mask away the hexit that we just printed, then keep looping.
316             // (We skip this when breaking out of the loop above, because _Adjusted_mantissa isn't used later.)
317             const _Uint_type _Mask = (_Uint_type{1} << _Number_of_bits_remaining) - 1;
318             _Adjusted_mantissa &= _Mask;
319         }
320     }
321 
322     // * Print the exponent.
323 
324     // C11 7.21.6.1 "The fprintf function"/8: "The exponent always contains at least one digit, and only as many more
325     // digits as necessary to represent the decimal exponent of 2."
326 
327     // Performance note: We should take advantage of the known ranges of possible exponents.
328 
329     *_First++ = 'p';
330     *_First++ = _Sign_character;
331 
332     // We've already printed '-' if necessary, so uint32_t _Absolute_exponent avoids testing that again.
333     return _VSTD::to_chars(_First, _Last, _Absolute_exponent);
334 }
335 
336 template <class _Floating>
337 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
338 to_chars_result _Floating_to_chars_hex_shortest(
339     char* _First, char* const _Last, const _Floating _Value) noexcept {
340 
341     // This prints "1.728p+0" instead of "2.e5p-1".
342     // This prints "0.000002p-126" instead of "1p-149" for float.
343     // This prints "0.0000000000001p-1022" instead of "1p-1074" for double.
344     // This prioritizes being consistent with printf's de facto behavior (and hex-precision's behavior)
345     // over minimizing the number of characters printed.
346 
347     using _Traits    = _Floating_type_traits<_Floating>;
348     using _Uint_type = typename _Traits::_Uint_type;
349 
350     const _Uint_type _Uint_value = _VSTD::bit_cast<_Uint_type>(_Value);
351 
352     if (_Uint_value == 0) { // zero detected; write "0p+0" and return
353         // C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
354         // Special-casing zero is necessary because of the exponent.
355         const char* const _Str = "0p+0";
356         const size_t _Len      = 4;
357 
358         if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
359             return {_Last, errc::value_too_large};
360         }
361 
362         _VSTD::memcpy(_First, _Str, _Len);
363 
364         return {_First + _Len, errc{}};
365     }
366 
367     const _Uint_type _Ieee_mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
368     const int32_t _Ieee_exponent    = static_cast<int32_t>(_Uint_value >> _Traits::_Exponent_shift);
369 
370     char _Leading_hexit; // implicit bit
371     int32_t _Unbiased_exponent;
372 
373     if (_Ieee_exponent == 0) { // subnormal
374         _Leading_hexit     = '0';
375         _Unbiased_exponent = 1 - _Traits::_Exponent_bias;
376     } else { // normal
377         _Leading_hexit     = '1';
378         _Unbiased_exponent = _Ieee_exponent - _Traits::_Exponent_bias;
379     }
380 
381     // Performance note: Consider avoiding per-character bounds checking when there's plenty of space.
382 
383     if (_First == _Last) {
384         return {_Last, errc::value_too_large};
385     }
386 
387     *_First++ = _Leading_hexit;
388 
389     if (_Ieee_mantissa == 0) {
390         // The fraction bits are all 0. Trim them away, including the decimal point.
391     } else {
392         if (_First == _Last) {
393             return {_Last, errc::value_too_large};
394         }
395 
396         *_First++ = '.';
397 
398         // The hexits after the decimal point correspond to the explicitly stored fraction bits.
399         // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, so we'll print at most 6 hexits.
400         // double explicitly stores 52 fraction bits. 52 / 4 == 13, so we'll print at most 13 hexits.
401         _Uint_type _Adjusted_mantissa;
402         int32_t _Number_of_bits_remaining;
403 
404         if constexpr (_IsSame<_Floating, float>::value) {
405             _Adjusted_mantissa        = _Ieee_mantissa << 1; // align to hexit boundary (23 isn't divisible by 4)
406             _Number_of_bits_remaining = 24; // 23 fraction bits + 1 alignment bit
407         } else {
408             _Adjusted_mantissa        = _Ieee_mantissa; // already aligned (52 is divisible by 4)
409             _Number_of_bits_remaining = 52; // 52 fraction bits
410         }
411 
412         // do-while: The condition _Adjusted_mantissa != 0 is initially true - we have nonzero fraction bits and we've
413         // printed the decimal point. Each iteration, we print a hexit, mask it away, and keep looping if we still have
414         // nonzero fraction bits. If there would be trailing '0' hexits, this trims them. If there wouldn't be trailing
415         // '0' hexits, the same condition works (as we print the final hexit and mask it away); we don't need to test
416         // _Number_of_bits_remaining.
417         do {
418             _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining >= 4, "");
419             _LIBCPP_ASSERT_UNCATEGORIZED(_Number_of_bits_remaining % 4 == 0, "");
420             _Number_of_bits_remaining -= 4;
421 
422             const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining);
423             _LIBCPP_ASSERT_UNCATEGORIZED(_Nibble < 16, "");
424             const char _Hexit = __itoa::_Charconv_digits[_Nibble];
425 
426             if (_First == _Last) {
427                 return {_Last, errc::value_too_large};
428             }
429 
430             *_First++ = _Hexit;
431 
432             const _Uint_type _Mask = (_Uint_type{1} << _Number_of_bits_remaining) - 1;
433             _Adjusted_mantissa &= _Mask;
434 
435         } while (_Adjusted_mantissa != 0);
436     }
437 
438     // C11 7.21.6.1 "The fprintf function"/8: "The exponent always contains at least one digit, and only as many more
439     // digits as necessary to represent the decimal exponent of 2."
440 
441     // Performance note: We should take advantage of the known ranges of possible exponents.
442 
443     // float: _Unbiased_exponent is within [-126, 127].
444     // double: _Unbiased_exponent is within [-1022, 1023].
445 
446     if (_Last - _First < 2) {
447         return {_Last, errc::value_too_large};
448     }
449 
450     *_First++ = 'p';
451 
452     if (_Unbiased_exponent < 0) {
453         *_First++          = '-';
454         _Unbiased_exponent = -_Unbiased_exponent;
455     } else {
456         *_First++ = '+';
457     }
458 
459     // We've already printed '-' if necessary, so static_cast<uint32_t> avoids testing that again.
460     return _VSTD::to_chars(_First, _Last, static_cast<uint32_t>(_Unbiased_exponent));
461 }
462 
463 // For general precision, we can use lookup tables to avoid performing trial formatting.
464 
465 // For a simple example, imagine counting the number of digits D in an integer, and needing to know
466 // whether D is less than 3, equal to 3/4/5/6, or greater than 6. We could use a lookup table:
467 // D | Largest integer with D digits
468 // 2 |      99
469 // 3 |     999
470 // 4 |   9'999
471 // 5 |  99'999
472 // 6 | 999'999
473 // 7 | table end
474 // Looking up an integer in this table with lower_bound() will work:
475 // * Too-small integers, like 7, 70, and 99, will cause lower_bound() to return the D == 2 row. (If all we care
476 //   about is whether D is less than 3, then it's okay to smash the D == 1 and D == 2 cases together.)
477 // * Integers in [100, 999] will cause lower_bound() to return the D == 3 row, and so forth.
478 // * Too-large integers, like 1'000'000 and above, will cause lower_bound() to return the end of the table. If we
479 //   compute D from that index, this will be considered D == 7, which will activate any "greater than 6" logic.
480 
481 // Floating-point is slightly more complicated.
482 
483 // The ordinary lookup tables are for X within [-5, 38] for float, and [-5, 308] for double.
484 // (-5 absorbs too-negative exponents, outside the P > X >= -4 criterion. 38 and 308 are the maximum exponents.)
485 // Due to the P > X condition, we can use a subset of the table for X within [-5, P - 1], suitably clamped.
486 
487 // When P is small, rounding can affect X. For example:
488 // For P == 1, the largest double with X == 0 is: 9.4999999999999982236431605997495353221893310546875
489 // For P == 2, the largest double with X == 0 is: 9.949999999999999289457264239899814128875732421875
490 // For P == 3, the largest double with X == 0 is: 9.9949999999999992184029906638897955417633056640625
491 
492 // Exponent adjustment is a concern for P within [1, 7] for float, and [1, 15] for double (determined via
493 // brute force). While larger values of P still perform rounding, they can't trigger exponent adjustment.
494 // This is because only values with repeated '9' digits can undergo exponent adjustment during rounding,
495 // and floating-point granularity limits the number of consecutive '9' digits that can appear.
496 
497 // So, we need special lookup tables for small values of P.
498 // These tables have varying lengths due to the P > X >= -4 criterion. For example:
499 // For P == 1, need table entries for X: -5, -4, -3, -2, -1, 0
500 // For P == 2, need table entries for X: -5, -4, -3, -2, -1, 0, 1
501 // For P == 3, need table entries for X: -5, -4, -3, -2, -1, 0, 1, 2
502 // For P == 4, need table entries for X: -5, -4, -3, -2, -1, 0, 1, 2, 3
503 
504 // We can concatenate these tables for compact storage, using triangular numbers to access them.
505 // The table for P begins at index (P - 1) * (P + 10) / 2 with length P + 5.
506 
507 // For both the ordinary and special lookup tables, after an index I is returned by lower_bound(), X is I - 5.
508 
509 // We need to special-case the floating-point value 0.0, which is considered to have X == 0.
510 // Otherwise, the lookup tables would consider it to have a highly negative X.
511 
512 // Finally, because we're working with positive floating-point values,
513 // representation comparisons behave identically to floating-point comparisons.
514 
515 // The following code generated the lookup tables for the scientific exponent X. Don't remove this code.
516 #if 0
517 // cl /EHsc /nologo /W4 /MT /O2 /std:c++17 generate_tables.cpp && generate_tables
518 
519 #include <algorithm>
520 #include <assert.h>
521 #include <charconv>
522 #include <cmath>
523 #include <limits>
524 #include <map>
525 #include <stdint.h>
526 #include <stdio.h>
527 #include <system_error>
528 #include <type_traits>
529 #include <vector>
530 using namespace std;
531 
532 template <typename UInt, typename Pred>
533 [[nodiscard]] UInt uint_partition_point(UInt first, const UInt last, Pred pred) {
534     // Find the beginning of the false partition in [first, last).
535     // [first, last) is partitioned when all of the true values occur before all of the false values.
536 
537     static_assert(is_unsigned_v<UInt>);
538     assert(first <= last);
539 
540     for (UInt n = last - first; n > 0;) {
541         const UInt n2  = n / 2;
542         const UInt mid = first + n2;
543 
544         if (pred(mid)) {
545             first = mid + 1;
546             n     = n - n2 - 1;
547         } else {
548             n = n2;
549         }
550     }
551 
552     return first;
553 }
554 
555 template <typename Floating>
556 [[nodiscard]] int scientific_exponent_X(const int P, const Floating flt) {
557     char buf[400]; // more than enough
558 
559     // C11 7.21.6.1 "The fprintf function"/8 performs trial formatting with scientific precision P - 1.
560     const auto to_result = to_chars(buf, end(buf), flt, chars_format::scientific, P - 1);
561     assert(to_result.ec == errc{});
562 
563     const char* exp_ptr = find(buf, to_result.ptr, 'e');
564     assert(exp_ptr != to_result.ptr);
565 
566     ++exp_ptr; // advance past 'e'
567 
568     if (*exp_ptr == '+') {
569         ++exp_ptr; // advance past '+' which from_chars() won't parse
570     }
571 
572     int X;
573     const auto from_result = from_chars(exp_ptr, to_result.ptr, X);
574     assert(from_result.ec == errc{});
575     return X;
576 }
577 
578 template <typename UInt>
579 void print_table(const vector<UInt>& v, const char* const name) {
580     constexpr const char* UIntName = _IsSame<UInt, uint32_t>::value ? "uint32_t" : "uint64_t";
581 
582     printf("static constexpr %s %s[%zu] = {\n", UIntName, name, v.size());
583 
584     for (const auto& val : v) {
585         if constexpr (_IsSame<UInt, uint32_t>::value) {
586             printf("0x%08Xu,\n", val);
587         } else {
588             printf("0x%016llXu,\n", val);
589         }
590     }
591 
592     printf("};\n");
593 }
594 
595 enum class Mode { Tables, Tests };
596 
597 template <typename Floating>
598 void generate_tables(const Mode mode) {
599     using Limits = numeric_limits<Floating>;
600     using UInt   = conditional_t<_IsSame<Floating, float>::value, uint32_t, uint64_t>;
601 
602     map<int, map<int, UInt>> P_X_LargestValWithX;
603 
604     constexpr int MaxP = Limits::max_exponent10 + 1; // MaxP performs no rounding during trial formatting
605 
606     for (int P = 1; P <= MaxP; ++P) {
607         for (int X = -5; X < P; ++X) {
608             constexpr Floating first = static_cast<Floating>(9e-5); // well below 9.5e-5, otherwise arbitrary
609             constexpr Floating last  = Limits::infinity(); // one bit above Limits::max()
610 
611             const UInt val_beyond_X = uint_partition_point(reinterpret_cast<const UInt&>(first),
612                 reinterpret_cast<const UInt&>(last),
613                 [P, X](const UInt u) { return scientific_exponent_X(P, reinterpret_cast<const Floating&>(u)) <= X; });
614 
615             P_X_LargestValWithX[P][X] = val_beyond_X - 1;
616         }
617     }
618 
619     constexpr const char* FloatingName = _IsSame<Floating, float>::value ? "float" : "double";
620 
621     constexpr int MaxSpecialP = _IsSame<Floating, float>::value ? 7 : 15; // MaxSpecialP is affected by exponent adjustment
622 
623     if (mode == Mode::Tables) {
624         printf("template <>\n");
625         printf("struct _General_precision_tables<%s> {\n", FloatingName);
626 
627         printf("static constexpr int _Max_special_P = %d;\n", MaxSpecialP);
628 
629         vector<UInt> special;
630 
631         for (int P = 1; P <= MaxSpecialP; ++P) {
632             for (int X = -5; X < P; ++X) {
633                 const UInt val = P_X_LargestValWithX[P][X];
634                 special.push_back(val);
635             }
636         }
637 
638         print_table(special, "_Special_X_table");
639 
640         for (int P = MaxSpecialP + 1; P < MaxP; ++P) {
641             for (int X = -5; X < P; ++X) {
642                 const UInt val = P_X_LargestValWithX[P][X];
643                 assert(val == P_X_LargestValWithX[MaxP][X]);
644             }
645         }
646 
647         printf("static constexpr int _Max_P = %d;\n", MaxP);
648 
649         vector<UInt> ordinary;
650 
651         for (int X = -5; X < MaxP; ++X) {
652             const UInt val = P_X_LargestValWithX[MaxP][X];
653             ordinary.push_back(val);
654         }
655 
656         print_table(ordinary, "_Ordinary_X_table");
657 
658         printf("};\n");
659     } else {
660         printf("==========\n");
661         printf("Test cases for %s:\n", FloatingName);
662 
663         constexpr int Hexits         = _IsSame<Floating, float>::value ? 6 : 13;
664         constexpr const char* Suffix = _IsSame<Floating, float>::value ? "f" : "";
665 
666         for (int P = 1; P <= MaxP; ++P) {
667             for (int X = -5; X < P; ++X) {
668                 if (P <= MaxSpecialP || P == 25 || P == MaxP || X == P - 1) {
669                     const UInt val1   = P_X_LargestValWithX[P][X];
670                     const Floating f1 = reinterpret_cast<const Floating&>(val1);
671                     const UInt val2   = val1 + 1;
672                     const Floating f2 = reinterpret_cast<const Floating&>(val2);
673 
674                     printf("{%.*a%s, chars_format::general, %d, \"%.*g\"},\n", Hexits, f1, Suffix, P, P, f1);
675                     if (isfinite(f2)) {
676                         printf("{%.*a%s, chars_format::general, %d, \"%.*g\"},\n", Hexits, f2, Suffix, P, P, f2);
677                     }
678                 }
679             }
680         }
681     }
682 }
683 
684 int main() {
685     printf("template <class _Floating>\n");
686     printf("struct _General_precision_tables;\n");
687     generate_tables<float>(Mode::Tables);
688     generate_tables<double>(Mode::Tables);
689     generate_tables<float>(Mode::Tests);
690     generate_tables<double>(Mode::Tests);
691 }
692 #endif // 0
693 
694 template <class _Floating>
695 struct _General_precision_tables;
696 
697 template <>
698 struct _General_precision_tables<float> {
699     static constexpr int _Max_special_P = 7;
700 
701     static constexpr uint32_t _Special_X_table[63] = {0x38C73ABCu, 0x3A79096Bu, 0x3C1BA5E3u, 0x3DC28F5Cu, 0x3F733333u,
702         0x4117FFFFu, 0x38D0AAA7u, 0x3A826AA8u, 0x3C230553u, 0x3DCBC6A7u, 0x3F7EB851u, 0x411F3333u, 0x42C6FFFFu,
703         0x38D19C3Fu, 0x3A8301A7u, 0x3C23C211u, 0x3DCCB295u, 0x3F7FDF3Bu, 0x411FEB85u, 0x42C7E666u, 0x4479DFFFu,
704         0x38D1B468u, 0x3A8310C1u, 0x3C23D4F1u, 0x3DCCCA2Du, 0x3F7FFCB9u, 0x411FFDF3u, 0x42C7FD70u, 0x4479FCCCu,
705         0x461C3DFFu, 0x38D1B6D2u, 0x3A831243u, 0x3C23D6D4u, 0x3DCCCC89u, 0x3F7FFFACu, 0x411FFFCBu, 0x42C7FFBEu,
706         0x4479FFAEu, 0x461C3FCCu, 0x47C34FBFu, 0x38D1B710u, 0x3A83126Au, 0x3C23D704u, 0x3DCCCCC6u, 0x3F7FFFF7u,
707         0x411FFFFAu, 0x42C7FFF9u, 0x4479FFF7u, 0x461C3FFAu, 0x47C34FF9u, 0x497423F7u, 0x38D1B716u, 0x3A83126Eu,
708         0x3C23D709u, 0x3DCCCCCCu, 0x3F7FFFFFu, 0x411FFFFFu, 0x42C7FFFFu, 0x4479FFFFu, 0x461C3FFFu, 0x47C34FFFu,
709         0x497423FFu, 0x4B18967Fu};
710 
711     static constexpr int _Max_P = 39;
712 
713     static constexpr uint32_t _Ordinary_X_table[44] = {0x38D1B717u, 0x3A83126Eu, 0x3C23D70Au, 0x3DCCCCCCu, 0x3F7FFFFFu,
714         0x411FFFFFu, 0x42C7FFFFu, 0x4479FFFFu, 0x461C3FFFu, 0x47C34FFFu, 0x497423FFu, 0x4B18967Fu, 0x4CBEBC1Fu,
715         0x4E6E6B27u, 0x501502F8u, 0x51BA43B7u, 0x5368D4A5u, 0x551184E7u, 0x56B5E620u, 0x58635FA9u, 0x5A0E1BC9u,
716         0x5BB1A2BCu, 0x5D5E0B6Bu, 0x5F0AC723u, 0x60AD78EBu, 0x6258D726u, 0x64078678u, 0x65A96816u, 0x6753C21Bu,
717         0x69045951u, 0x6AA56FA5u, 0x6C4ECB8Fu, 0x6E013F39u, 0x6FA18F07u, 0x7149F2C9u, 0x72FC6F7Cu, 0x749DC5ADu,
718         0x76453719u, 0x77F684DFu, 0x799A130Bu, 0x7B4097CEu, 0x7CF0BDC2u, 0x7E967699u, 0x7F7FFFFFu};
719 };
720 
721 template <>
722 struct _General_precision_tables<double> {
723     static constexpr int _Max_special_P = 15;
724 
725     static constexpr uint64_t _Special_X_table[195] = {0x3F18E757928E0C9Du, 0x3F4F212D77318FC5u, 0x3F8374BC6A7EF9DBu,
726         0x3FB851EB851EB851u, 0x3FEE666666666666u, 0x4022FFFFFFFFFFFFu, 0x3F1A1554FBDAD751u, 0x3F504D551D68C692u,
727         0x3F8460AA64C2F837u, 0x3FB978D4FDF3B645u, 0x3FEFD70A3D70A3D7u, 0x4023E66666666666u, 0x4058DFFFFFFFFFFFu,
728         0x3F1A3387ECC8EB96u, 0x3F506034F3FD933Eu, 0x3F84784230FCF80Du, 0x3FB99652BD3C3611u, 0x3FEFFBE76C8B4395u,
729         0x4023FD70A3D70A3Du, 0x4058FCCCCCCCCCCCu, 0x408F3BFFFFFFFFFFu, 0x3F1A368D04E0BA6Au, 0x3F506218230C7482u,
730         0x3F847A9E2BCF91A3u, 0x3FB99945B6C3760Bu, 0x3FEFFF972474538Eu, 0x4023FFBE76C8B439u, 0x4058FFAE147AE147u,
731         0x408F3F9999999999u, 0x40C387BFFFFFFFFFu, 0x3F1A36DA54164F19u, 0x3F506248748DF16Fu, 0x3F847ADA91B16DCBu,
732         0x3FB99991361DC93Eu, 0x3FEFFFF583A53B8Eu, 0x4023FFF972474538u, 0x4058FFF7CED91687u, 0x408F3FF5C28F5C28u,
733         0x40C387F999999999u, 0x40F869F7FFFFFFFFu, 0x3F1A36E20F35445Du, 0x3F50624D49814ABAu, 0x3F847AE09BE19D69u,
734         0x3FB99998C2DA04C3u, 0x3FEFFFFEF39085F4u, 0x4023FFFF583A53B8u, 0x4058FFFF2E48E8A7u, 0x408F3FFEF9DB22D0u,
735         0x40C387FF5C28F5C2u, 0x40F869FF33333333u, 0x412E847EFFFFFFFFu, 0x3F1A36E2D51EC34Bu, 0x3F50624DC5333A0Eu,
736         0x3F847AE136800892u, 0x3FB9999984200AB7u, 0x3FEFFFFFE5280D65u, 0x4023FFFFEF39085Fu, 0x4058FFFFEB074A77u,
737         0x408F3FFFE5C91D14u, 0x40C387FFEF9DB22Du, 0x40F869FFEB851EB8u, 0x412E847FE6666666u, 0x416312CFEFFFFFFFu,
738         0x3F1A36E2E8E94FFCu, 0x3F50624DD191D1FDu, 0x3F847AE145F6467Du, 0x3FB999999773D81Cu, 0x3FEFFFFFFD50CE23u,
739         0x4023FFFFFE5280D6u, 0x4058FFFFFDE7210Bu, 0x408F3FFFFD60E94Eu, 0x40C387FFFE5C91D1u, 0x40F869FFFDF3B645u,
740         0x412E847FFD70A3D7u, 0x416312CFFE666666u, 0x4197D783FDFFFFFFu, 0x3F1A36E2EAE3F7A7u, 0x3F50624DD2CE7AC8u,
741         0x3F847AE14782197Bu, 0x3FB9999999629FD9u, 0x3FEFFFFFFFBB47D0u, 0x4023FFFFFFD50CE2u, 0x4058FFFFFFCA501Au,
742         0x408F3FFFFFBCE421u, 0x40C387FFFFD60E94u, 0x40F869FFFFCB923Au, 0x412E847FFFBE76C8u, 0x416312CFFFD70A3Du,
743         0x4197D783FFCCCCCCu, 0x41CDCD64FFBFFFFFu, 0x3F1A36E2EB16A205u, 0x3F50624DD2EE2543u, 0x3F847AE147A9AE94u,
744         0x3FB9999999941A39u, 0x3FEFFFFFFFF920C8u, 0x4023FFFFFFFBB47Du, 0x4058FFFFFFFAA19Cu, 0x408F3FFFFFF94A03u,
745         0x40C387FFFFFBCE42u, 0x40F869FFFFFAC1D2u, 0x412E847FFFF97247u, 0x416312CFFFFBE76Cu, 0x4197D783FFFAE147u,
746         0x41CDCD64FFF99999u, 0x4202A05F1FFBFFFFu, 0x3F1A36E2EB1BB30Fu, 0x3F50624DD2F14FE9u, 0x3F847AE147ADA3E3u,
747         0x3FB9999999990CDCu, 0x3FEFFFFFFFFF5014u, 0x4023FFFFFFFF920Cu, 0x4058FFFFFFFF768Fu, 0x408F3FFFFFFF5433u,
748         0x40C387FFFFFF94A0u, 0x40F869FFFFFF79C8u, 0x412E847FFFFF583Au, 0x416312CFFFFF9724u, 0x4197D783FFFF7CEDu,
749         0x41CDCD64FFFF5C28u, 0x4202A05F1FFF9999u, 0x42374876E7FF7FFFu, 0x3F1A36E2EB1C34C3u, 0x3F50624DD2F1A0FAu,
750         0x3F847AE147AE0938u, 0x3FB9999999998B86u, 0x3FEFFFFFFFFFEE68u, 0x4023FFFFFFFFF501u, 0x4058FFFFFFFFF241u,
751         0x408F3FFFFFFFEED1u, 0x40C387FFFFFFF543u, 0x40F869FFFFFFF294u, 0x412E847FFFFFEF39u, 0x416312CFFFFFF583u,
752         0x4197D783FFFFF2E4u, 0x41CDCD64FFFFEF9Du, 0x4202A05F1FFFF5C2u, 0x42374876E7FFF333u, 0x426D1A94A1FFEFFFu,
753         0x3F1A36E2EB1C41BBu, 0x3F50624DD2F1A915u, 0x3F847AE147AE135Au, 0x3FB9999999999831u, 0x3FEFFFFFFFFFFE3Du,
754         0x4023FFFFFFFFFEE6u, 0x4058FFFFFFFFFEA0u, 0x408F3FFFFFFFFE48u, 0x40C387FFFFFFFEEDu, 0x40F869FFFFFFFEA8u,
755         0x412E847FFFFFFE52u, 0x416312CFFFFFFEF3u, 0x4197D783FFFFFEB0u, 0x41CDCD64FFFFFE5Cu, 0x4202A05F1FFFFEF9u,
756         0x42374876E7FFFEB8u, 0x426D1A94A1FFFE66u, 0x42A2309CE53FFEFFu, 0x3F1A36E2EB1C4307u, 0x3F50624DD2F1A9E4u,
757         0x3F847AE147AE145Eu, 0x3FB9999999999975u, 0x3FEFFFFFFFFFFFD2u, 0x4023FFFFFFFFFFE3u, 0x4058FFFFFFFFFFDCu,
758         0x408F3FFFFFFFFFD4u, 0x40C387FFFFFFFFE4u, 0x40F869FFFFFFFFDDu, 0x412E847FFFFFFFD5u, 0x416312CFFFFFFFE5u,
759         0x4197D783FFFFFFDEu, 0x41CDCD64FFFFFFD6u, 0x4202A05F1FFFFFE5u, 0x42374876E7FFFFDFu, 0x426D1A94A1FFFFD7u,
760         0x42A2309CE53FFFE6u, 0x42D6BCC41E8FFFDFu, 0x3F1A36E2EB1C4328u, 0x3F50624DD2F1A9F9u, 0x3F847AE147AE1477u,
761         0x3FB9999999999995u, 0x3FEFFFFFFFFFFFFBu, 0x4023FFFFFFFFFFFDu, 0x4058FFFFFFFFFFFCu, 0x408F3FFFFFFFFFFBu,
762         0x40C387FFFFFFFFFDu, 0x40F869FFFFFFFFFCu, 0x412E847FFFFFFFFBu, 0x416312CFFFFFFFFDu, 0x4197D783FFFFFFFCu,
763         0x41CDCD64FFFFFFFBu, 0x4202A05F1FFFFFFDu, 0x42374876E7FFFFFCu, 0x426D1A94A1FFFFFBu, 0x42A2309CE53FFFFDu,
764         0x42D6BCC41E8FFFFCu, 0x430C6BF52633FFFBu};
765 
766     static constexpr int _Max_P = 309;
767 
768     static constexpr uint64_t _Ordinary_X_table[314] = {0x3F1A36E2EB1C432Cu, 0x3F50624DD2F1A9FBu, 0x3F847AE147AE147Au,
769         0x3FB9999999999999u, 0x3FEFFFFFFFFFFFFFu, 0x4023FFFFFFFFFFFFu, 0x4058FFFFFFFFFFFFu, 0x408F3FFFFFFFFFFFu,
770         0x40C387FFFFFFFFFFu, 0x40F869FFFFFFFFFFu, 0x412E847FFFFFFFFFu, 0x416312CFFFFFFFFFu, 0x4197D783FFFFFFFFu,
771         0x41CDCD64FFFFFFFFu, 0x4202A05F1FFFFFFFu, 0x42374876E7FFFFFFu, 0x426D1A94A1FFFFFFu, 0x42A2309CE53FFFFFu,
772         0x42D6BCC41E8FFFFFu, 0x430C6BF52633FFFFu, 0x4341C37937E07FFFu, 0x4376345785D89FFFu, 0x43ABC16D674EC7FFu,
773         0x43E158E460913CFFu, 0x4415AF1D78B58C3Fu, 0x444B1AE4D6E2EF4Fu, 0x4480F0CF064DD591u, 0x44B52D02C7E14AF6u,
774         0x44EA784379D99DB4u, 0x45208B2A2C280290u, 0x4554ADF4B7320334u, 0x4589D971E4FE8401u, 0x45C027E72F1F1281u,
775         0x45F431E0FAE6D721u, 0x46293E5939A08CE9u, 0x465F8DEF8808B024u, 0x4693B8B5B5056E16u, 0x46C8A6E32246C99Cu,
776         0x46FED09BEAD87C03u, 0x4733426172C74D82u, 0x476812F9CF7920E2u, 0x479E17B84357691Bu, 0x47D2CED32A16A1B1u,
777         0x48078287F49C4A1Du, 0x483D6329F1C35CA4u, 0x48725DFA371A19E6u, 0x48A6F578C4E0A060u, 0x48DCB2D6F618C878u,
778         0x4911EFC659CF7D4Bu, 0x49466BB7F0435C9Eu, 0x497C06A5EC5433C6u, 0x49B18427B3B4A05Bu, 0x49E5E531A0A1C872u,
779         0x4A1B5E7E08CA3A8Fu, 0x4A511B0EC57E6499u, 0x4A8561D276DDFDC0u, 0x4ABABA4714957D30u, 0x4AF0B46C6CDD6E3Eu,
780         0x4B24E1878814C9CDu, 0x4B5A19E96A19FC40u, 0x4B905031E2503DA8u, 0x4BC4643E5AE44D12u, 0x4BF97D4DF19D6057u,
781         0x4C2FDCA16E04B86Du, 0x4C63E9E4E4C2F344u, 0x4C98E45E1DF3B015u, 0x4CCF1D75A5709C1Au, 0x4D03726987666190u,
782         0x4D384F03E93FF9F4u, 0x4D6E62C4E38FF872u, 0x4DA2FDBB0E39FB47u, 0x4DD7BD29D1C87A19u, 0x4E0DAC74463A989Fu,
783         0x4E428BC8ABE49F63u, 0x4E772EBAD6DDC73Cu, 0x4EACFA698C95390Bu, 0x4EE21C81F7DD43A7u, 0x4F16A3A275D49491u,
784         0x4F4C4C8B1349B9B5u, 0x4F81AFD6EC0E1411u, 0x4FB61BCCA7119915u, 0x4FEBA2BFD0D5FF5Bu, 0x502145B7E285BF98u,
785         0x50559725DB272F7Fu, 0x508AFCEF51F0FB5Eu, 0x50C0DE1593369D1Bu, 0x50F5159AF8044462u, 0x512A5B01B605557Au,
786         0x516078E111C3556Cu, 0x5194971956342AC7u, 0x51C9BCDFABC13579u, 0x5200160BCB58C16Cu, 0x52341B8EBE2EF1C7u,
787         0x526922726DBAAE39u, 0x529F6B0F092959C7u, 0x52D3A2E965B9D81Cu, 0x53088BA3BF284E23u, 0x533EAE8CAEF261ACu,
788         0x53732D17ED577D0Bu, 0x53A7F85DE8AD5C4Eu, 0x53DDF67562D8B362u, 0x5412BA095DC7701Du, 0x5447688BB5394C25u,
789         0x547D42AEA2879F2Eu, 0x54B249AD2594C37Cu, 0x54E6DC186EF9F45Cu, 0x551C931E8AB87173u, 0x5551DBF316B346E7u,
790         0x558652EFDC6018A1u, 0x55BBE7ABD3781ECAu, 0x55F170CB642B133Eu, 0x5625CCFE3D35D80Eu, 0x565B403DCC834E11u,
791         0x569108269FD210CBu, 0x56C54A3047C694FDu, 0x56FA9CBC59B83A3Du, 0x5730A1F5B8132466u, 0x5764CA732617ED7Fu,
792         0x5799FD0FEF9DE8DFu, 0x57D03E29F5C2B18Bu, 0x58044DB473335DEEu, 0x583961219000356Au, 0x586FB969F40042C5u,
793         0x58A3D3E2388029BBu, 0x58D8C8DAC6A0342Au, 0x590EFB1178484134u, 0x59435CEAEB2D28C0u, 0x59783425A5F872F1u,
794         0x59AE412F0F768FADu, 0x59E2E8BD69AA19CCu, 0x5A17A2ECC414A03Fu, 0x5A4D8BA7F519C84Fu, 0x5A827748F9301D31u,
795         0x5AB7151B377C247Eu, 0x5AECDA62055B2D9Du, 0x5B22087D4358FC82u, 0x5B568A9C942F3BA3u, 0x5B8C2D43B93B0A8Bu,
796         0x5BC19C4A53C4E697u, 0x5BF6035CE8B6203Du, 0x5C2B843422E3A84Cu, 0x5C6132A095CE492Fu, 0x5C957F48BB41DB7Bu,
797         0x5CCADF1AEA12525Au, 0x5D00CB70D24B7378u, 0x5D34FE4D06DE5056u, 0x5D6A3DE04895E46Cu, 0x5DA066AC2D5DAEC3u,
798         0x5DD4805738B51A74u, 0x5E09A06D06E26112u, 0x5E400444244D7CABu, 0x5E7405552D60DBD6u, 0x5EA906AA78B912CBu,
799         0x5EDF485516E7577Eu, 0x5F138D352E5096AFu, 0x5F48708279E4BC5Au, 0x5F7E8CA3185DEB71u, 0x5FB317E5EF3AB327u,
800         0x5FE7DDDF6B095FF0u, 0x601DD55745CBB7ECu, 0x6052A5568B9F52F4u, 0x60874EAC2E8727B1u, 0x60BD22573A28F19Du,
801         0x60F2357684599702u, 0x6126C2D4256FFCC2u, 0x615C73892ECBFBF3u, 0x6191C835BD3F7D78u, 0x61C63A432C8F5CD6u,
802         0x61FBC8D3F7B3340Bu, 0x62315D847AD00087u, 0x6265B4E5998400A9u, 0x629B221EFFE500D3u, 0x62D0F5535FEF2084u,
803         0x630532A837EAE8A5u, 0x633A7F5245E5A2CEu, 0x63708F936BAF85C1u, 0x63A4B378469B6731u, 0x63D9E056584240FDu,
804         0x64102C35F729689Eu, 0x6444374374F3C2C6u, 0x647945145230B377u, 0x64AF965966BCE055u, 0x64E3BDF7E0360C35u,
805         0x6518AD75D8438F43u, 0x654ED8D34E547313u, 0x6583478410F4C7ECu, 0x65B819651531F9E7u, 0x65EE1FBE5A7E7861u,
806         0x6622D3D6F88F0B3Cu, 0x665788CCB6B2CE0Cu, 0x668D6AFFE45F818Fu, 0x66C262DFEEBBB0F9u, 0x66F6FB97EA6A9D37u,
807         0x672CBA7DE5054485u, 0x6761F48EAF234AD3u, 0x679671B25AEC1D88u, 0x67CC0E1EF1A724EAu, 0x680188D357087712u,
808         0x6835EB082CCA94D7u, 0x686B65CA37FD3A0Du, 0x68A11F9E62FE4448u, 0x68D56785FBBDD55Au, 0x690AC1677AAD4AB0u,
809         0x6940B8E0ACAC4EAEu, 0x6974E718D7D7625Au, 0x69AA20DF0DCD3AF0u, 0x69E0548B68A044D6u, 0x6A1469AE42C8560Cu,
810         0x6A498419D37A6B8Fu, 0x6A7FE52048590672u, 0x6AB3EF342D37A407u, 0x6AE8EB0138858D09u, 0x6B1F25C186A6F04Cu,
811         0x6B537798F428562Fu, 0x6B88557F31326BBBu, 0x6BBE6ADEFD7F06AAu, 0x6BF302CB5E6F642Au, 0x6C27C37E360B3D35u,
812         0x6C5DB45DC38E0C82u, 0x6C9290BA9A38C7D1u, 0x6CC734E940C6F9C5u, 0x6CFD022390F8B837u, 0x6D3221563A9B7322u,
813         0x6D66A9ABC9424FEBu, 0x6D9C5416BB92E3E6u, 0x6DD1B48E353BCE6Fu, 0x6E0621B1C28AC20Bu, 0x6E3BAA1E332D728Eu,
814         0x6E714A52DFFC6799u, 0x6EA59CE797FB817Fu, 0x6EDB04217DFA61DFu, 0x6F10E294EEBC7D2Bu, 0x6F451B3A2A6B9C76u,
815         0x6F7A6208B5068394u, 0x6FB07D457124123Cu, 0x6FE49C96CD6D16CBu, 0x7019C3BC80C85C7Eu, 0x70501A55D07D39CFu,
816         0x708420EB449C8842u, 0x70B9292615C3AA53u, 0x70EF736F9B3494E8u, 0x7123A825C100DD11u, 0x7158922F31411455u,
817         0x718EB6BAFD91596Bu, 0x71C33234DE7AD7E2u, 0x71F7FEC216198DDBu, 0x722DFE729B9FF152u, 0x7262BF07A143F6D3u,
818         0x72976EC98994F488u, 0x72CD4A7BEBFA31AAu, 0x73024E8D737C5F0Au, 0x7336E230D05B76CDu, 0x736C9ABD04725480u,
819         0x73A1E0B622C774D0u, 0x73D658E3AB795204u, 0x740BEF1C9657A685u, 0x74417571DDF6C813u, 0x7475D2CE55747A18u,
820         0x74AB4781EAD1989Eu, 0x74E10CB132C2FF63u, 0x75154FDD7F73BF3Bu, 0x754AA3D4DF50AF0Au, 0x7580A6650B926D66u,
821         0x75B4CFFE4E7708C0u, 0x75EA03FDE214CAF0u, 0x7620427EAD4CFED6u, 0x7654531E58A03E8Bu, 0x768967E5EEC84E2Eu,
822         0x76BFC1DF6A7A61BAu, 0x76F3D92BA28C7D14u, 0x7728CF768B2F9C59u, 0x775F03542DFB8370u, 0x779362149CBD3226u,
823         0x77C83A99C3EC7EAFu, 0x77FE494034E79E5Bu, 0x7832EDC82110C2F9u, 0x7867A93A2954F3B7u, 0x789D9388B3AA30A5u,
824         0x78D27C35704A5E67u, 0x79071B42CC5CF601u, 0x793CE2137F743381u, 0x79720D4C2FA8A030u, 0x79A6909F3B92C83Du,
825         0x79DC34C70A777A4Cu, 0x7A11A0FC668AAC6Fu, 0x7A46093B802D578Bu, 0x7A7B8B8A6038AD6Eu, 0x7AB137367C236C65u,
826         0x7AE585041B2C477Eu, 0x7B1AE64521F7595Eu, 0x7B50CFEB353A97DAu, 0x7B8503E602893DD1u, 0x7BBA44DF832B8D45u,
827         0x7BF06B0BB1FB384Bu, 0x7C2485CE9E7A065Eu, 0x7C59A742461887F6u, 0x7C9008896BCF54F9u, 0x7CC40AABC6C32A38u,
828         0x7CF90D56B873F4C6u, 0x7D2F50AC6690F1F8u, 0x7D63926BC01A973Bu, 0x7D987706B0213D09u, 0x7DCE94C85C298C4Cu,
829         0x7E031CFD3999F7AFu, 0x7E37E43C8800759Bu, 0x7E6DDD4BAA009302u, 0x7EA2AA4F4A405BE1u, 0x7ED754E31CD072D9u,
830         0x7F0D2A1BE4048F90u, 0x7F423A516E82D9BAu, 0x7F76C8E5CA239028u, 0x7FAC7B1F3CAC7433u, 0x7FE1CCF385EBC89Fu,
831         0x7FEFFFFFFFFFFFFFu};
832 };
833 
834 template <class _Floating>
835 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
836 to_chars_result _Floating_to_chars_general_precision(
837     char* _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
838 
839     using _Traits    = _Floating_type_traits<_Floating>;
840     using _Uint_type = typename _Traits::_Uint_type;
841 
842     const _Uint_type _Uint_value = _VSTD::bit_cast<_Uint_type>(_Value);
843 
844     if (_Uint_value == 0) { // zero detected; write "0" and return; _Precision is irrelevant due to zero-trimming
845         if (_First == _Last) {
846             return {_Last, errc::value_too_large};
847         }
848 
849         *_First++ = '0';
850 
851         return {_First, errc{}};
852     }
853 
854     // C11 7.21.6.1 "The fprintf function"/5:
855     // "A negative precision argument is taken as if the precision were omitted."
856     // /8: "g,G [...] Let P equal the precision if nonzero, 6 if the precision is omitted,
857     // or 1 if the precision is zero."
858 
859     // Performance note: It's possible to rewrite this for branchless codegen,
860     // but profiling will be necessary to determine whether that's faster.
861     if (_Precision < 0) {
862         _Precision = 6;
863     } else if (_Precision == 0) {
864         _Precision = 1;
865     } else if (_Precision < 1'000'000) {
866         // _Precision is ok.
867     } else {
868         // Avoid integer overflow.
869         // Due to general notation's zero-trimming behavior, we can simply clamp _Precision.
870         // This is further clamped below.
871         _Precision = 1'000'000;
872     }
873 
874     // _Precision is now the Standard's P.
875 
876     // /8: "Then, if a conversion with style E would have an exponent of X:
877     // - if P > X >= -4, the conversion is with style f (or F) and precision P - (X + 1).
878     // - otherwise, the conversion is with style e (or E) and precision P - 1."
879 
880     // /8: "Finally, [...] any trailing zeros are removed from the fractional portion of the result
881     // and the decimal-point character is removed if there is no fractional portion remaining."
882 
883     using _Tables = _General_precision_tables<_Floating>;
884 
885     const _Uint_type* _Table_begin;
886     const _Uint_type* _Table_end;
887 
888     if (_Precision <= _Tables::_Max_special_P) {
889         _Table_begin = _Tables::_Special_X_table + (_Precision - 1) * (_Precision + 10) / 2;
890         _Table_end   = _Table_begin + _Precision + 5;
891     } else {
892         _Table_begin = _Tables::_Ordinary_X_table;
893         _Table_end   = _Table_begin + _VSTD::min(_Precision, _Tables::_Max_P) + 5;
894     }
895 
896     // Profiling indicates that linear search is faster than binary search for small tables.
897     // Performance note: lambda captures may have a small performance cost.
898     const _Uint_type* const _Table_lower_bound = [=] {
899         if constexpr (!_IsSame<_Floating, float>::value) {
900             if (_Precision > 155) { // threshold determined via profiling
901                 return _VSTD::lower_bound(_Table_begin, _Table_end, _Uint_value, less{});
902             }
903         }
904 
905         return _VSTD::find_if(_Table_begin, _Table_end, [=](const _Uint_type _Elem) { return _Uint_value <= _Elem; });
906     }();
907 
908     const ptrdiff_t _Table_index     = _Table_lower_bound - _Table_begin;
909     const int _Scientific_exponent_X = static_cast<int>(_Table_index - 5);
910     const bool _Use_fixed_notation   = _Precision > _Scientific_exponent_X && _Scientific_exponent_X >= -4;
911 
912     // Performance note: it might (or might not) be faster to modify Ryu Printf to perform zero-trimming.
913     // Such modifications would involve a fairly complicated state machine (notably, both '0' and '9' digits would
914     // need to be buffered, due to rounding), and that would have performance costs due to increased branching.
915     // Here, we're using a simpler approach: writing into a local buffer, manually zero-trimming, and then copying into
916     // the output range. The necessary buffer size is reasonably small, the zero-trimming logic is simple and fast,
917     // and the final copying is also fast.
918 
919     constexpr int _Max_output_length =
920         _IsSame<_Floating, float>::value ? 117 : 773; // cases: 0x1.fffffep-126f and 0x1.fffffffffffffp-1022
921     constexpr int _Max_fixed_precision =
922         _IsSame<_Floating, float>::value ? 37 : 66; // cases: 0x1.fffffep-14f and 0x1.fffffffffffffp-14
923     constexpr int _Max_scientific_precision =
924         _IsSame<_Floating, float>::value ? 111 : 766; // cases: 0x1.fffffep-126f and 0x1.fffffffffffffp-1022
925 
926     // Note that _Max_output_length is determined by scientific notation and is more than enough for fixed notation.
927     // 0x1.fffffep+127f is 39 digits, plus 1 for '.', plus _Max_fixed_precision for '0' digits, equals 77.
928     // 0x1.fffffffffffffp+1023 is 309 digits, plus 1 for '.', plus _Max_fixed_precision for '0' digits, equals 376.
929 
930     char _Buffer[_Max_output_length];
931     const char* const _Significand_first = _Buffer; // e.g. "1.234"
932     const char* _Significand_last        = nullptr;
933     const char* _Exponent_first          = nullptr; // e.g. "e-05"
934     const char* _Exponent_last           = nullptr;
935     int _Effective_precision; // number of digits printed after the decimal point, before trimming
936 
937     // Write into the local buffer.
938     // Clamping _Effective_precision allows _Buffer to be as small as possible, and increases efficiency.
939     if (_Use_fixed_notation) {
940         _Effective_precision = _VSTD::min(_Precision - (_Scientific_exponent_X + 1), _Max_fixed_precision);
941         const to_chars_result _Buf_result =
942             _Floating_to_chars_fixed_precision(_Buffer, _VSTD::end(_Buffer), _Value, _Effective_precision);
943         _LIBCPP_ASSERT_UNCATEGORIZED(_Buf_result.ec == errc{}, "");
944         _Significand_last = _Buf_result.ptr;
945     } else {
946         _Effective_precision = _VSTD::min(_Precision - 1, _Max_scientific_precision);
947         const to_chars_result _Buf_result =
948             _Floating_to_chars_scientific_precision(_Buffer, _VSTD::end(_Buffer), _Value, _Effective_precision);
949         _LIBCPP_ASSERT_UNCATEGORIZED(_Buf_result.ec == errc{}, "");
950         _Significand_last = _VSTD::find(_Buffer, _Buf_result.ptr, 'e');
951         _Exponent_first   = _Significand_last;
952         _Exponent_last    = _Buf_result.ptr;
953     }
954 
955     // If we printed a decimal point followed by digits, perform zero-trimming.
956     if (_Effective_precision > 0) {
957         while (_Significand_last[-1] == '0') { // will stop at '.' or a nonzero digit
958             --_Significand_last;
959         }
960 
961         if (_Significand_last[-1] == '.') {
962             --_Significand_last;
963         }
964     }
965 
966     // Copy the significand to the output range.
967     const ptrdiff_t _Significand_distance = _Significand_last - _Significand_first;
968     if (_Last - _First < _Significand_distance) {
969         return {_Last, errc::value_too_large};
970     }
971     _VSTD::memcpy(_First, _Significand_first, static_cast<size_t>(_Significand_distance));
972     _First += _Significand_distance;
973 
974     // Copy the exponent to the output range.
975     if (!_Use_fixed_notation) {
976         const ptrdiff_t _Exponent_distance = _Exponent_last - _Exponent_first;
977         if (_Last - _First < _Exponent_distance) {
978             return {_Last, errc::value_too_large};
979         }
980         _VSTD::memcpy(_First, _Exponent_first, static_cast<size_t>(_Exponent_distance));
981         _First += _Exponent_distance;
982     }
983 
984     return {_First, errc{}};
985 }
986 
987 enum class _Floating_to_chars_overload { _Plain, _Format_only, _Format_precision };
988 
989 template <_Floating_to_chars_overload _Overload, class _Floating>
990 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
991 to_chars_result _Floating_to_chars(
992     char* _First, char* const _Last, _Floating _Value, const chars_format _Fmt, const int _Precision) noexcept {
993 
994     if constexpr (_Overload == _Floating_to_chars_overload::_Plain) {
995         _LIBCPP_ASSERT_UNCATEGORIZED(_Fmt == chars_format{}, ""); // plain overload must pass chars_format{} internally
996     } else {
997         _LIBCPP_ASSERT_UNCATEGORIZED(_Fmt == chars_format::general || _Fmt == chars_format::scientific
998                          || _Fmt == chars_format::fixed || _Fmt == chars_format::hex,
999             "invalid format in to_chars()");
1000     }
1001 
1002     using _Traits    = _Floating_type_traits<_Floating>;
1003     using _Uint_type = typename _Traits::_Uint_type;
1004 
1005     _Uint_type _Uint_value = _VSTD::bit_cast<_Uint_type>(_Value);
1006 
1007     const bool _Was_negative = (_Uint_value & _Traits::_Shifted_sign_mask) != 0;
1008 
1009     if (_Was_negative) { // sign bit detected; write minus sign and clear sign bit
1010         if (_First == _Last) {
1011             return {_Last, errc::value_too_large};
1012         }
1013 
1014         *_First++ = '-';
1015 
1016         _Uint_value &= ~_Traits::_Shifted_sign_mask;
1017         _Value = _VSTD::bit_cast<_Floating>(_Uint_value);
1018     }
1019 
1020     if ((_Uint_value & _Traits::_Shifted_exponent_mask) == _Traits::_Shifted_exponent_mask) {
1021         // inf/nan detected; write appropriate string and return
1022         const char* _Str;
1023         size_t _Len;
1024 
1025         const _Uint_type _Mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
1026 
1027         if (_Mantissa == 0) {
1028             _Str = "inf";
1029             _Len = 3;
1030         } else if (_Was_negative && _Mantissa == _Traits::_Special_nan_mantissa_mask) {
1031             // When a NaN value has the sign bit set, the quiet bit set, and all other mantissa bits cleared,
1032             // the UCRT interprets it to mean "indeterminate", and indicates this by printing "-nan(ind)".
1033             _Str = "nan(ind)";
1034             _Len = 8;
1035         } else if ((_Mantissa & _Traits::_Special_nan_mantissa_mask) != 0) {
1036             _Str = "nan";
1037             _Len = 3;
1038         } else {
1039             _Str = "nan(snan)";
1040             _Len = 9;
1041         }
1042 
1043         if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
1044             return {_Last, errc::value_too_large};
1045         }
1046 
1047         _VSTD::memcpy(_First, _Str, _Len);
1048 
1049         return {_First + _Len, errc{}};
1050     }
1051 
1052     if constexpr (_Overload == _Floating_to_chars_overload::_Plain) {
1053         return _Floating_to_chars_ryu(_First, _Last, _Value, chars_format{});
1054     } else if constexpr (_Overload == _Floating_to_chars_overload::_Format_only) {
1055         if (_Fmt == chars_format::hex) {
1056             return _Floating_to_chars_hex_shortest(_First, _Last, _Value);
1057         }
1058 
1059         return _Floating_to_chars_ryu(_First, _Last, _Value, _Fmt);
1060     } else if constexpr (_Overload == _Floating_to_chars_overload::_Format_precision) {
1061         switch (_Fmt) {
1062         case chars_format::scientific:
1063             return _Floating_to_chars_scientific_precision(_First, _Last, _Value, _Precision);
1064         case chars_format::fixed:
1065             return _Floating_to_chars_fixed_precision(_First, _Last, _Value, _Precision);
1066         case chars_format::general:
1067             return _Floating_to_chars_general_precision(_First, _Last, _Value, _Precision);
1068         case chars_format::hex:
1069         default: // avoid MSVC warning C4715: not all control paths return a value
1070             return _Floating_to_chars_hex_precision(_First, _Last, _Value, _Precision);
1071         }
1072     }
1073 }
1074 
1075 // clang-format on
1076 
1077 _LIBCPP_END_NAMESPACE_STD
1078 
1079 #endif // _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
1080