xref: /freebsd-src/contrib/llvm-project/libcxx/src/include/to_chars_floating_point.h (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
10eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric 
90eae32dcSDimitry Andric // Copyright (c) Microsoft Corporation.
100eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
110eae32dcSDimitry Andric 
120eae32dcSDimitry Andric // This implementation is dedicated to the memory of Mary and Thavatchai.
130eae32dcSDimitry Andric 
140eae32dcSDimitry Andric #ifndef _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
150eae32dcSDimitry Andric #define _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
160eae32dcSDimitry Andric 
170eae32dcSDimitry Andric // Avoid formatting to keep the changes with the original code minimal.
180eae32dcSDimitry Andric // clang-format off
190eae32dcSDimitry Andric 
2081ad6265SDimitry Andric #include <__algorithm/find.h>
2181ad6265SDimitry Andric #include <__algorithm/find_if.h>
2281ad6265SDimitry Andric #include <__algorithm/lower_bound.h>
2381ad6265SDimitry Andric #include <__algorithm/min.h>
2481ad6265SDimitry Andric #include <__assert>
2581ad6265SDimitry Andric #include <__config>
2681ad6265SDimitry Andric #include <__functional/operations.h>
2781ad6265SDimitry Andric #include <__iterator/access.h>
2881ad6265SDimitry Andric #include <__iterator/size.h>
2981ad6265SDimitry Andric #include <bit>
3081ad6265SDimitry Andric #include <cfloat>
3181ad6265SDimitry Andric #include <climits>
3281ad6265SDimitry Andric 
330eae32dcSDimitry Andric #include "include/ryu/ryu.h"
340eae32dcSDimitry Andric 
350eae32dcSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
360eae32dcSDimitry Andric 
370eae32dcSDimitry Andric namespace __itoa {
380eae32dcSDimitry Andric inline constexpr char _Charconv_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
390eae32dcSDimitry Andric     'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
405f757f3fSDimitry Andric static_assert(std::size(_Charconv_digits) == 36);
410eae32dcSDimitry Andric } // __itoa
420eae32dcSDimitry Andric 
430eae32dcSDimitry Andric // vvvvvvvvvv DERIVED FROM corecrt_internal_fltintrn.h vvvvvvvvvv
440eae32dcSDimitry Andric 
450eae32dcSDimitry Andric template <class _FloatingType>
460eae32dcSDimitry Andric struct _Floating_type_traits;
470eae32dcSDimitry Andric 
480eae32dcSDimitry Andric template <>
490eae32dcSDimitry Andric struct _Floating_type_traits<float> {
500eae32dcSDimitry Andric     static constexpr int32_t _Mantissa_bits = FLT_MANT_DIG;
510eae32dcSDimitry Andric     static constexpr int32_t _Exponent_bits = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
520eae32dcSDimitry Andric 
530eae32dcSDimitry Andric     static constexpr int32_t _Maximum_binary_exponent = FLT_MAX_EXP - 1;
540eae32dcSDimitry Andric     static constexpr int32_t _Minimum_binary_exponent = FLT_MIN_EXP - 1;
550eae32dcSDimitry Andric 
560eae32dcSDimitry Andric     static constexpr int32_t _Exponent_bias = 127;
570eae32dcSDimitry Andric 
580eae32dcSDimitry Andric     static constexpr int32_t _Sign_shift     = _Exponent_bits + _Mantissa_bits - 1;
590eae32dcSDimitry Andric     static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1;
600eae32dcSDimitry Andric 
610eae32dcSDimitry Andric     using _Uint_type = uint32_t;
620eae32dcSDimitry Andric 
630eae32dcSDimitry Andric     static constexpr uint32_t _Exponent_mask             = (1u << _Exponent_bits) - 1;
640eae32dcSDimitry Andric     static constexpr uint32_t _Normal_mantissa_mask      = (1u << _Mantissa_bits) - 1;
650eae32dcSDimitry Andric     static constexpr uint32_t _Denormal_mantissa_mask    = (1u << (_Mantissa_bits - 1)) - 1;
660eae32dcSDimitry Andric     static constexpr uint32_t _Special_nan_mantissa_mask = 1u << (_Mantissa_bits - 2);
670eae32dcSDimitry Andric     static constexpr uint32_t _Shifted_sign_mask         = 1u << _Sign_shift;
680eae32dcSDimitry Andric     static constexpr uint32_t _Shifted_exponent_mask     = _Exponent_mask << _Exponent_shift;
690eae32dcSDimitry Andric };
700eae32dcSDimitry Andric 
710eae32dcSDimitry Andric template <>
720eae32dcSDimitry Andric struct _Floating_type_traits<double> {
730eae32dcSDimitry Andric     static constexpr int32_t _Mantissa_bits = DBL_MANT_DIG;
740eae32dcSDimitry Andric     static constexpr int32_t _Exponent_bits = sizeof(double) * CHAR_BIT - DBL_MANT_DIG;
750eae32dcSDimitry Andric 
760eae32dcSDimitry Andric     static constexpr int32_t _Maximum_binary_exponent = DBL_MAX_EXP - 1;
770eae32dcSDimitry Andric     static constexpr int32_t _Minimum_binary_exponent = DBL_MIN_EXP - 1;
780eae32dcSDimitry Andric 
790eae32dcSDimitry Andric     static constexpr int32_t _Exponent_bias = 1023;
800eae32dcSDimitry Andric 
810eae32dcSDimitry Andric     static constexpr int32_t _Sign_shift     = _Exponent_bits + _Mantissa_bits - 1;
820eae32dcSDimitry Andric     static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1;
830eae32dcSDimitry Andric 
840eae32dcSDimitry Andric     using _Uint_type = uint64_t;
850eae32dcSDimitry Andric 
860eae32dcSDimitry Andric     static constexpr uint64_t _Exponent_mask             = (1ULL << _Exponent_bits) - 1;
870eae32dcSDimitry Andric     static constexpr uint64_t _Normal_mantissa_mask      = (1ULL << _Mantissa_bits) - 1;
880eae32dcSDimitry Andric     static constexpr uint64_t _Denormal_mantissa_mask    = (1ULL << (_Mantissa_bits - 1)) - 1;
890eae32dcSDimitry Andric     static constexpr uint64_t _Special_nan_mantissa_mask = 1ULL << (_Mantissa_bits - 2);
900eae32dcSDimitry Andric     static constexpr uint64_t _Shifted_sign_mask         = 1ULL << _Sign_shift;
910eae32dcSDimitry Andric     static constexpr uint64_t _Shifted_exponent_mask     = _Exponent_mask << _Exponent_shift;
920eae32dcSDimitry Andric };
930eae32dcSDimitry Andric 
940eae32dcSDimitry Andric // ^^^^^^^^^^ DERIVED FROM corecrt_internal_fltintrn.h ^^^^^^^^^^
950eae32dcSDimitry Andric 
960eae32dcSDimitry Andric // FUNCTION to_chars (FLOATING-POINT TO STRING)
970eae32dcSDimitry Andric template <class _Floating>
980eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
990eae32dcSDimitry Andric to_chars_result _Floating_to_chars_hex_precision(
1000eae32dcSDimitry Andric     char* _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
1010eae32dcSDimitry Andric 
1020eae32dcSDimitry Andric     // * Determine the effective _Precision.
1030eae32dcSDimitry Andric     // * Later, we'll decrement _Precision when printing each hexit after the decimal point.
1040eae32dcSDimitry Andric 
1050eae32dcSDimitry Andric     // The hexits after the decimal point correspond to the explicitly stored fraction bits.
1060eae32dcSDimitry Andric     // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, which is 6 hexits.
1070eae32dcSDimitry Andric     // double explicitly stores 52 fraction bits. 52 / 4 == 13, which is 13 hexits.
1080eae32dcSDimitry Andric     constexpr int _Full_precision         = _IsSame<_Floating, float>::value ? 6 : 13;
1090eae32dcSDimitry Andric     constexpr int _Adjusted_explicit_bits = _Full_precision * 4;
1100eae32dcSDimitry Andric 
1110eae32dcSDimitry Andric     if (_Precision < 0) {
1120eae32dcSDimitry Andric         // C11 7.21.6.1 "The fprintf function"/5: "A negative precision argument is taken as if the precision were
1130eae32dcSDimitry Andric         // omitted." /8: "if the precision is missing and FLT_RADIX is a power of 2, then the precision is sufficient
1140eae32dcSDimitry Andric         // for an exact representation of the value"
1150eae32dcSDimitry Andric         _Precision = _Full_precision;
1160eae32dcSDimitry Andric     }
1170eae32dcSDimitry Andric 
1180eae32dcSDimitry Andric     // * Extract the _Ieee_mantissa and _Ieee_exponent.
1190eae32dcSDimitry Andric     using _Traits    = _Floating_type_traits<_Floating>;
1200eae32dcSDimitry Andric     using _Uint_type = typename _Traits::_Uint_type;
1210eae32dcSDimitry Andric 
1225f757f3fSDimitry Andric     const _Uint_type _Uint_value    = std::bit_cast<_Uint_type>(_Value);
1230eae32dcSDimitry Andric     const _Uint_type _Ieee_mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
1240eae32dcSDimitry Andric     const int32_t _Ieee_exponent    = static_cast<int32_t>(_Uint_value >> _Traits::_Exponent_shift);
1250eae32dcSDimitry Andric 
1260eae32dcSDimitry Andric     // * Prepare the _Adjusted_mantissa. This is aligned to hexit boundaries,
1270eae32dcSDimitry Andric     // * with the implicit bit restored (0 for zero values and subnormal values, 1 for normal values).
1280eae32dcSDimitry Andric     // * Also calculate the _Unbiased_exponent. This unifies the processing of zero, subnormal, and normal values.
1290eae32dcSDimitry Andric     _Uint_type _Adjusted_mantissa;
1300eae32dcSDimitry Andric 
1310eae32dcSDimitry Andric     if constexpr (_IsSame<_Floating, float>::value) {
1320eae32dcSDimitry Andric         _Adjusted_mantissa = _Ieee_mantissa << 1; // align to hexit boundary (23 isn't divisible by 4)
1330eae32dcSDimitry Andric     } else {
1340eae32dcSDimitry Andric         _Adjusted_mantissa = _Ieee_mantissa; // already aligned (52 is divisible by 4)
1350eae32dcSDimitry Andric     }
1360eae32dcSDimitry Andric 
1370eae32dcSDimitry Andric     int32_t _Unbiased_exponent;
1380eae32dcSDimitry Andric 
1390eae32dcSDimitry Andric     if (_Ieee_exponent == 0) { // zero or subnormal
1400eae32dcSDimitry Andric         // implicit bit is 0
1410eae32dcSDimitry Andric 
1420eae32dcSDimitry Andric         if (_Ieee_mantissa == 0) { // zero
1430eae32dcSDimitry Andric             // C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
1440eae32dcSDimitry Andric             _Unbiased_exponent = 0;
1450eae32dcSDimitry Andric         } else { // subnormal
1460eae32dcSDimitry Andric             _Unbiased_exponent = 1 - _Traits::_Exponent_bias;
1470eae32dcSDimitry Andric         }
1480eae32dcSDimitry Andric     } else { // normal
1490eae32dcSDimitry Andric         _Adjusted_mantissa |= _Uint_type{1} << _Adjusted_explicit_bits; // implicit bit is 1
1500eae32dcSDimitry Andric         _Unbiased_exponent = _Ieee_exponent - _Traits::_Exponent_bias;
1510eae32dcSDimitry Andric     }
1520eae32dcSDimitry Andric 
1530eae32dcSDimitry Andric     // _Unbiased_exponent is within [-126, 127] for float, [-1022, 1023] for double.
1540eae32dcSDimitry Andric 
1550eae32dcSDimitry Andric     // * Decompose _Unbiased_exponent into _Sign_character and _Absolute_exponent.
1560eae32dcSDimitry Andric     char _Sign_character;
1570eae32dcSDimitry Andric     uint32_t _Absolute_exponent;
1580eae32dcSDimitry Andric 
1590eae32dcSDimitry Andric     if (_Unbiased_exponent < 0) {
1600eae32dcSDimitry Andric         _Sign_character    = '-';
1610eae32dcSDimitry Andric         _Absolute_exponent = static_cast<uint32_t>(-_Unbiased_exponent);
1620eae32dcSDimitry Andric     } else {
1630eae32dcSDimitry Andric         _Sign_character    = '+';
1640eae32dcSDimitry Andric         _Absolute_exponent = static_cast<uint32_t>(_Unbiased_exponent);
1650eae32dcSDimitry Andric     }
1660eae32dcSDimitry Andric 
1670eae32dcSDimitry Andric     // _Absolute_exponent is within [0, 127] for float, [0, 1023] for double.
1680eae32dcSDimitry Andric 
1690eae32dcSDimitry Andric     // * Perform a single bounds check.
1700eae32dcSDimitry Andric     {
1710eae32dcSDimitry Andric         int32_t _Exponent_length;
1720eae32dcSDimitry Andric 
1730eae32dcSDimitry Andric         if (_Absolute_exponent < 10) {
1740eae32dcSDimitry Andric             _Exponent_length = 1;
1750eae32dcSDimitry Andric         } else if (_Absolute_exponent < 100) {
1760eae32dcSDimitry Andric             _Exponent_length = 2;
1770eae32dcSDimitry Andric         } else if constexpr (_IsSame<_Floating, float>::value) {
1780eae32dcSDimitry Andric             _Exponent_length = 3;
1790eae32dcSDimitry Andric         } else if (_Absolute_exponent < 1000) {
1800eae32dcSDimitry Andric             _Exponent_length = 3;
1810eae32dcSDimitry Andric         } else {
1820eae32dcSDimitry Andric             _Exponent_length = 4;
1830eae32dcSDimitry Andric         }
1840eae32dcSDimitry Andric 
1850eae32dcSDimitry Andric         // _Precision might be enormous; avoid integer overflow by testing it separately.
1860eae32dcSDimitry Andric         ptrdiff_t _Buffer_size = _Last - _First;
1870eae32dcSDimitry Andric 
1880eae32dcSDimitry Andric         if (_Buffer_size < _Precision) {
1890eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
1900eae32dcSDimitry Andric         }
1910eae32dcSDimitry Andric 
1920eae32dcSDimitry Andric         _Buffer_size -= _Precision;
1930eae32dcSDimitry Andric 
1940eae32dcSDimitry Andric         const int32_t _Length_excluding_precision = 1 // leading hexit
1950eae32dcSDimitry Andric                                                     + static_cast<int32_t>(_Precision > 0) // possible decimal point
1960eae32dcSDimitry Andric                                                     // excluding `+ _Precision`, hexits after decimal point
1970eae32dcSDimitry Andric                                                     + 2 // "p+" or "p-"
1980eae32dcSDimitry Andric                                                     + _Exponent_length; // exponent
1990eae32dcSDimitry Andric 
2000eae32dcSDimitry Andric         if (_Buffer_size < _Length_excluding_precision) {
2010eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
2020eae32dcSDimitry Andric         }
2030eae32dcSDimitry Andric     }
2040eae32dcSDimitry Andric 
2050eae32dcSDimitry Andric     // * Perform rounding when we've been asked to omit hexits.
2060eae32dcSDimitry Andric     if (_Precision < _Full_precision) {
2070eae32dcSDimitry Andric         // _Precision is within [0, 5] for float, [0, 12] for double.
2080eae32dcSDimitry Andric 
2090eae32dcSDimitry Andric         // _Dropped_bits is within [4, 24] for float, [4, 52] for double.
2100eae32dcSDimitry Andric         const int _Dropped_bits = (_Full_precision - _Precision) * 4;
2110eae32dcSDimitry Andric 
2120eae32dcSDimitry Andric         // Perform rounding by adding an appropriately-shifted bit.
2130eae32dcSDimitry Andric 
2140eae32dcSDimitry Andric         // This can propagate carries all the way into the leading hexit. Examples:
2150eae32dcSDimitry Andric         // "0.ff9" rounded to a precision of 2 is "1.00".
2160eae32dcSDimitry Andric         // "1.ff9" rounded to a precision of 2 is "2.00".
2170eae32dcSDimitry Andric 
2180eae32dcSDimitry Andric         // Note that the leading hexit participates in the rounding decision. Examples:
2190eae32dcSDimitry Andric         // "0.8" rounded to a precision of 0 is "0".
2200eae32dcSDimitry Andric         // "1.8" rounded to a precision of 0 is "2".
2210eae32dcSDimitry Andric 
2220eae32dcSDimitry Andric         // Reference implementation with suboptimal codegen:
2230eae32dcSDimitry Andric         // bool _Should_round_up(bool _Lsb_bit, bool _Round_bit, bool _Has_tail_bits) {
2240eae32dcSDimitry Andric         //    // If there are no insignificant set bits, the value is exactly-representable and should not be rounded.
2250eae32dcSDimitry Andric         //    //
2260eae32dcSDimitry Andric         //    // If there are insignificant set bits, we need to round according to round_to_nearest.
2270eae32dcSDimitry Andric         //    // We need to handle two cases: we round up if either [1] the value is slightly greater
2280eae32dcSDimitry Andric         //    // than the midpoint between two exactly-representable values or [2] the value is exactly the midpoint
2290eae32dcSDimitry Andric         //    // between two exactly-representable values and the greater of the two is even (this is "round-to-even").
2300eae32dcSDimitry Andric         //    return _Round_bit && (_Has_tail_bits || _Lsb_bit);
2310eae32dcSDimitry Andric         //}
2320eae32dcSDimitry Andric         // const bool _Lsb_bit       = (_Adjusted_mantissa & (_Uint_type{1} << _Dropped_bits)) != 0;
2330eae32dcSDimitry Andric         // const bool _Round_bit     = (_Adjusted_mantissa & (_Uint_type{1} << (_Dropped_bits - 1))) != 0;
2340eae32dcSDimitry Andric         // const bool _Has_tail_bits = (_Adjusted_mantissa & ((_Uint_type{1} << (_Dropped_bits - 1)) - 1)) != 0;
2350eae32dcSDimitry Andric         // const bool _Should_round = _Should_round_up(_Lsb_bit, _Round_bit, _Has_tail_bits);
2360eae32dcSDimitry Andric         // _Adjusted_mantissa += _Uint_type{_Should_round} << _Dropped_bits;
2370eae32dcSDimitry Andric 
2380eae32dcSDimitry Andric         // Example for optimized implementation: Let _Dropped_bits be 8.
2390eae32dcSDimitry Andric         //          Bit index: ...[8]76543210
2400eae32dcSDimitry Andric         // _Adjusted_mantissa: ...[L]RTTTTTTT (not depicting known details, like hexit alignment)
2410eae32dcSDimitry Andric         // By focusing on the bit at index _Dropped_bits, we can avoid unnecessary branching and shifting.
2420eae32dcSDimitry Andric 
2430eae32dcSDimitry Andric         // Bit index: ...[8]76543210
2440eae32dcSDimitry Andric         //  _Lsb_bit: ...[L]RTTTTTTT
2450eae32dcSDimitry Andric         const _Uint_type _Lsb_bit = _Adjusted_mantissa;
2460eae32dcSDimitry Andric 
2470eae32dcSDimitry Andric         //  Bit index: ...9[8]76543210
2480eae32dcSDimitry Andric         // _Round_bit: ...L[R]TTTTTTT0
2490eae32dcSDimitry Andric         const _Uint_type _Round_bit = _Adjusted_mantissa << 1;
2500eae32dcSDimitry Andric 
2510eae32dcSDimitry Andric         // We can detect (without branching) whether any of the trailing bits are set.
2520eae32dcSDimitry Andric         // Due to _Should_round below, this computation will be used if and only if R is 1, so we can assume that here.
2530eae32dcSDimitry Andric         //      Bit index: ...9[8]76543210
2540eae32dcSDimitry Andric         //     _Round_bit: ...L[1]TTTTTTT0
2550eae32dcSDimitry Andric         // _Has_tail_bits: ....[H]........
2560eae32dcSDimitry Andric 
2570eae32dcSDimitry Andric         // If all of the trailing bits T are 0, then `_Round_bit - 1` will produce 0 for H (due to R being 1).
2580eae32dcSDimitry Andric         // If any of the trailing bits T are 1, then `_Round_bit - 1` will produce 1 for H (due to R being 1).
2590eae32dcSDimitry Andric         const _Uint_type _Has_tail_bits = _Round_bit - 1;
2600eae32dcSDimitry Andric 
2610eae32dcSDimitry Andric         // Finally, we can use _Should_round_up() logic with bitwise-AND and bitwise-OR,
2620eae32dcSDimitry Andric         // selecting just the bit at index _Dropped_bits. This is the appropriately-shifted bit that we want.
2630eae32dcSDimitry Andric         const _Uint_type _Should_round = _Round_bit & (_Has_tail_bits | _Lsb_bit) & (_Uint_type{1} << _Dropped_bits);
2640eae32dcSDimitry Andric 
2650eae32dcSDimitry Andric         // This rounding technique is dedicated to the memory of Peppermint. =^..^=
2660eae32dcSDimitry Andric         _Adjusted_mantissa += _Should_round;
2670eae32dcSDimitry Andric     }
2680eae32dcSDimitry Andric 
2690eae32dcSDimitry Andric     // * Print the leading hexit, then mask it away.
2700eae32dcSDimitry Andric     {
2710eae32dcSDimitry Andric         const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Adjusted_explicit_bits);
2721db9f3b2SDimitry Andric         _LIBCPP_ASSERT_INTERNAL(_Nibble < 3, "");
2730eae32dcSDimitry Andric         const char _Leading_hexit = static_cast<char>('0' + _Nibble);
2740eae32dcSDimitry Andric 
2750eae32dcSDimitry Andric         *_First++ = _Leading_hexit;
2760eae32dcSDimitry Andric 
2770eae32dcSDimitry Andric         constexpr _Uint_type _Mask = (_Uint_type{1} << _Adjusted_explicit_bits) - 1;
2780eae32dcSDimitry Andric         _Adjusted_mantissa &= _Mask;
2790eae32dcSDimitry Andric     }
2800eae32dcSDimitry Andric 
2810eae32dcSDimitry Andric     // * Print the decimal point and trailing hexits.
2820eae32dcSDimitry Andric 
2830eae32dcSDimitry Andric     // C11 7.21.6.1 "The fprintf function"/8:
2840eae32dcSDimitry Andric     // "if the precision is zero and the # flag is not specified, no decimal-point character appears."
2850eae32dcSDimitry Andric     if (_Precision > 0) {
2860eae32dcSDimitry Andric         *_First++ = '.';
2870eae32dcSDimitry Andric 
2880eae32dcSDimitry Andric         int32_t _Number_of_bits_remaining = _Adjusted_explicit_bits; // 24 for float, 52 for double
2890eae32dcSDimitry Andric 
2900eae32dcSDimitry Andric         for (;;) {
2911db9f3b2SDimitry Andric             _LIBCPP_ASSERT_INTERNAL(_Number_of_bits_remaining >= 4, "");
2921db9f3b2SDimitry Andric             _LIBCPP_ASSERT_INTERNAL(_Number_of_bits_remaining % 4 == 0, "");
2930eae32dcSDimitry Andric             _Number_of_bits_remaining -= 4;
2940eae32dcSDimitry Andric 
2950eae32dcSDimitry Andric             const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining);
2961db9f3b2SDimitry Andric             _LIBCPP_ASSERT_INTERNAL(_Nibble < 16, "");
2970eae32dcSDimitry Andric             const char _Hexit = __itoa::_Charconv_digits[_Nibble];
2980eae32dcSDimitry Andric 
2990eae32dcSDimitry Andric             *_First++ = _Hexit;
3000eae32dcSDimitry Andric 
3010eae32dcSDimitry Andric             // _Precision is the number of hexits that still need to be printed.
3020eae32dcSDimitry Andric             --_Precision;
3030eae32dcSDimitry Andric             if (_Precision == 0) {
3040eae32dcSDimitry Andric                 break; // We're completely done with this phase.
3050eae32dcSDimitry Andric             }
3060eae32dcSDimitry Andric             // Otherwise, we need to keep printing hexits.
3070eae32dcSDimitry Andric 
3080eae32dcSDimitry Andric             if (_Number_of_bits_remaining == 0) {
3090eae32dcSDimitry Andric                 // We've finished printing _Adjusted_mantissa, so all remaining hexits are '0'.
3105f757f3fSDimitry Andric                 std::memset(_First, '0', static_cast<size_t>(_Precision));
3110eae32dcSDimitry Andric                 _First += _Precision;
3120eae32dcSDimitry Andric                 break;
3130eae32dcSDimitry Andric             }
3140eae32dcSDimitry Andric 
3150eae32dcSDimitry Andric             // Mask away the hexit that we just printed, then keep looping.
3160eae32dcSDimitry Andric             // (We skip this when breaking out of the loop above, because _Adjusted_mantissa isn't used later.)
3170eae32dcSDimitry Andric             const _Uint_type _Mask = (_Uint_type{1} << _Number_of_bits_remaining) - 1;
3180eae32dcSDimitry Andric             _Adjusted_mantissa &= _Mask;
3190eae32dcSDimitry Andric         }
3200eae32dcSDimitry Andric     }
3210eae32dcSDimitry Andric 
3220eae32dcSDimitry Andric     // * Print the exponent.
3230eae32dcSDimitry Andric 
3240eae32dcSDimitry Andric     // C11 7.21.6.1 "The fprintf function"/8: "The exponent always contains at least one digit, and only as many more
3250eae32dcSDimitry Andric     // digits as necessary to represent the decimal exponent of 2."
3260eae32dcSDimitry Andric 
3270eae32dcSDimitry Andric     // Performance note: We should take advantage of the known ranges of possible exponents.
3280eae32dcSDimitry Andric 
3290eae32dcSDimitry Andric     *_First++ = 'p';
3300eae32dcSDimitry Andric     *_First++ = _Sign_character;
3310eae32dcSDimitry Andric 
3320eae32dcSDimitry Andric     // We've already printed '-' if necessary, so uint32_t _Absolute_exponent avoids testing that again.
3335f757f3fSDimitry Andric     return std::to_chars(_First, _Last, _Absolute_exponent);
3340eae32dcSDimitry Andric }
3350eae32dcSDimitry Andric 
3360eae32dcSDimitry Andric template <class _Floating>
3370eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
3380eae32dcSDimitry Andric to_chars_result _Floating_to_chars_hex_shortest(
3390eae32dcSDimitry Andric     char* _First, char* const _Last, const _Floating _Value) noexcept {
3400eae32dcSDimitry Andric 
3410eae32dcSDimitry Andric     // This prints "1.728p+0" instead of "2.e5p-1".
3420eae32dcSDimitry Andric     // This prints "0.000002p-126" instead of "1p-149" for float.
3430eae32dcSDimitry Andric     // This prints "0.0000000000001p-1022" instead of "1p-1074" for double.
3440eae32dcSDimitry Andric     // This prioritizes being consistent with printf's de facto behavior (and hex-precision's behavior)
3450eae32dcSDimitry Andric     // over minimizing the number of characters printed.
3460eae32dcSDimitry Andric 
3470eae32dcSDimitry Andric     using _Traits    = _Floating_type_traits<_Floating>;
3480eae32dcSDimitry Andric     using _Uint_type = typename _Traits::_Uint_type;
3490eae32dcSDimitry Andric 
3505f757f3fSDimitry Andric     const _Uint_type _Uint_value = std::bit_cast<_Uint_type>(_Value);
3510eae32dcSDimitry Andric 
3520eae32dcSDimitry Andric     if (_Uint_value == 0) { // zero detected; write "0p+0" and return
3530eae32dcSDimitry Andric         // C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
3540eae32dcSDimitry Andric         // Special-casing zero is necessary because of the exponent.
3550eae32dcSDimitry Andric         const char* const _Str = "0p+0";
3560eae32dcSDimitry Andric         const size_t _Len      = 4;
3570eae32dcSDimitry Andric 
3580eae32dcSDimitry Andric         if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
3590eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
3600eae32dcSDimitry Andric         }
3610eae32dcSDimitry Andric 
3625f757f3fSDimitry Andric         std::memcpy(_First, _Str, _Len);
3630eae32dcSDimitry Andric 
3640eae32dcSDimitry Andric         return {_First + _Len, errc{}};
3650eae32dcSDimitry Andric     }
3660eae32dcSDimitry Andric 
3670eae32dcSDimitry Andric     const _Uint_type _Ieee_mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
3680eae32dcSDimitry Andric     const int32_t _Ieee_exponent    = static_cast<int32_t>(_Uint_value >> _Traits::_Exponent_shift);
3690eae32dcSDimitry Andric 
3700eae32dcSDimitry Andric     char _Leading_hexit; // implicit bit
3710eae32dcSDimitry Andric     int32_t _Unbiased_exponent;
3720eae32dcSDimitry Andric 
3730eae32dcSDimitry Andric     if (_Ieee_exponent == 0) { // subnormal
3740eae32dcSDimitry Andric         _Leading_hexit     = '0';
3750eae32dcSDimitry Andric         _Unbiased_exponent = 1 - _Traits::_Exponent_bias;
3760eae32dcSDimitry Andric     } else { // normal
3770eae32dcSDimitry Andric         _Leading_hexit     = '1';
3780eae32dcSDimitry Andric         _Unbiased_exponent = _Ieee_exponent - _Traits::_Exponent_bias;
3790eae32dcSDimitry Andric     }
3800eae32dcSDimitry Andric 
3810eae32dcSDimitry Andric     // Performance note: Consider avoiding per-character bounds checking when there's plenty of space.
3820eae32dcSDimitry Andric 
3830eae32dcSDimitry Andric     if (_First == _Last) {
3840eae32dcSDimitry Andric         return {_Last, errc::value_too_large};
3850eae32dcSDimitry Andric     }
3860eae32dcSDimitry Andric 
3870eae32dcSDimitry Andric     *_First++ = _Leading_hexit;
3880eae32dcSDimitry Andric 
3890eae32dcSDimitry Andric     if (_Ieee_mantissa == 0) {
3900eae32dcSDimitry Andric         // The fraction bits are all 0. Trim them away, including the decimal point.
3910eae32dcSDimitry Andric     } else {
3920eae32dcSDimitry Andric         if (_First == _Last) {
3930eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
3940eae32dcSDimitry Andric         }
3950eae32dcSDimitry Andric 
3960eae32dcSDimitry Andric         *_First++ = '.';
3970eae32dcSDimitry Andric 
3980eae32dcSDimitry Andric         // The hexits after the decimal point correspond to the explicitly stored fraction bits.
3990eae32dcSDimitry Andric         // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, so we'll print at most 6 hexits.
4000eae32dcSDimitry Andric         // double explicitly stores 52 fraction bits. 52 / 4 == 13, so we'll print at most 13 hexits.
4010eae32dcSDimitry Andric         _Uint_type _Adjusted_mantissa;
4020eae32dcSDimitry Andric         int32_t _Number_of_bits_remaining;
4030eae32dcSDimitry Andric 
4040eae32dcSDimitry Andric         if constexpr (_IsSame<_Floating, float>::value) {
4050eae32dcSDimitry Andric             _Adjusted_mantissa        = _Ieee_mantissa << 1; // align to hexit boundary (23 isn't divisible by 4)
4060eae32dcSDimitry Andric             _Number_of_bits_remaining = 24; // 23 fraction bits + 1 alignment bit
4070eae32dcSDimitry Andric         } else {
4080eae32dcSDimitry Andric             _Adjusted_mantissa        = _Ieee_mantissa; // already aligned (52 is divisible by 4)
4090eae32dcSDimitry Andric             _Number_of_bits_remaining = 52; // 52 fraction bits
4100eae32dcSDimitry Andric         }
4110eae32dcSDimitry Andric 
4120eae32dcSDimitry Andric         // do-while: The condition _Adjusted_mantissa != 0 is initially true - we have nonzero fraction bits and we've
4130eae32dcSDimitry Andric         // printed the decimal point. Each iteration, we print a hexit, mask it away, and keep looping if we still have
4140eae32dcSDimitry Andric         // nonzero fraction bits. If there would be trailing '0' hexits, this trims them. If there wouldn't be trailing
4150eae32dcSDimitry Andric         // '0' hexits, the same condition works (as we print the final hexit and mask it away); we don't need to test
4160eae32dcSDimitry Andric         // _Number_of_bits_remaining.
4170eae32dcSDimitry Andric         do {
4181db9f3b2SDimitry Andric             _LIBCPP_ASSERT_INTERNAL(_Number_of_bits_remaining >= 4, "");
4191db9f3b2SDimitry Andric             _LIBCPP_ASSERT_INTERNAL(_Number_of_bits_remaining % 4 == 0, "");
4200eae32dcSDimitry Andric             _Number_of_bits_remaining -= 4;
4210eae32dcSDimitry Andric 
4220eae32dcSDimitry Andric             const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining);
4231db9f3b2SDimitry Andric             _LIBCPP_ASSERT_INTERNAL(_Nibble < 16, "");
4240eae32dcSDimitry Andric             const char _Hexit = __itoa::_Charconv_digits[_Nibble];
4250eae32dcSDimitry Andric 
4260eae32dcSDimitry Andric             if (_First == _Last) {
4270eae32dcSDimitry Andric                 return {_Last, errc::value_too_large};
4280eae32dcSDimitry Andric             }
4290eae32dcSDimitry Andric 
4300eae32dcSDimitry Andric             *_First++ = _Hexit;
4310eae32dcSDimitry Andric 
4320eae32dcSDimitry Andric             const _Uint_type _Mask = (_Uint_type{1} << _Number_of_bits_remaining) - 1;
4330eae32dcSDimitry Andric             _Adjusted_mantissa &= _Mask;
4340eae32dcSDimitry Andric 
4350eae32dcSDimitry Andric         } while (_Adjusted_mantissa != 0);
4360eae32dcSDimitry Andric     }
4370eae32dcSDimitry Andric 
4380eae32dcSDimitry Andric     // C11 7.21.6.1 "The fprintf function"/8: "The exponent always contains at least one digit, and only as many more
4390eae32dcSDimitry Andric     // digits as necessary to represent the decimal exponent of 2."
4400eae32dcSDimitry Andric 
4410eae32dcSDimitry Andric     // Performance note: We should take advantage of the known ranges of possible exponents.
4420eae32dcSDimitry Andric 
4430eae32dcSDimitry Andric     // float: _Unbiased_exponent is within [-126, 127].
4440eae32dcSDimitry Andric     // double: _Unbiased_exponent is within [-1022, 1023].
4450eae32dcSDimitry Andric 
4460eae32dcSDimitry Andric     if (_Last - _First < 2) {
4470eae32dcSDimitry Andric         return {_Last, errc::value_too_large};
4480eae32dcSDimitry Andric     }
4490eae32dcSDimitry Andric 
4500eae32dcSDimitry Andric     *_First++ = 'p';
4510eae32dcSDimitry Andric 
4520eae32dcSDimitry Andric     if (_Unbiased_exponent < 0) {
4530eae32dcSDimitry Andric         *_First++          = '-';
4540eae32dcSDimitry Andric         _Unbiased_exponent = -_Unbiased_exponent;
4550eae32dcSDimitry Andric     } else {
4560eae32dcSDimitry Andric         *_First++ = '+';
4570eae32dcSDimitry Andric     }
4580eae32dcSDimitry Andric 
4590eae32dcSDimitry Andric     // We've already printed '-' if necessary, so static_cast<uint32_t> avoids testing that again.
4605f757f3fSDimitry Andric     return std::to_chars(_First, _Last, static_cast<uint32_t>(_Unbiased_exponent));
4610eae32dcSDimitry Andric }
4620eae32dcSDimitry Andric 
4630eae32dcSDimitry Andric // For general precision, we can use lookup tables to avoid performing trial formatting.
4640eae32dcSDimitry Andric 
4650eae32dcSDimitry Andric // For a simple example, imagine counting the number of digits D in an integer, and needing to know
4660eae32dcSDimitry Andric // whether D is less than 3, equal to 3/4/5/6, or greater than 6. We could use a lookup table:
4670eae32dcSDimitry Andric // D | Largest integer with D digits
4680eae32dcSDimitry Andric // 2 |      99
4690eae32dcSDimitry Andric // 3 |     999
4700eae32dcSDimitry Andric // 4 |   9'999
4710eae32dcSDimitry Andric // 5 |  99'999
4720eae32dcSDimitry Andric // 6 | 999'999
4730eae32dcSDimitry Andric // 7 | table end
4740eae32dcSDimitry Andric // Looking up an integer in this table with lower_bound() will work:
4750eae32dcSDimitry Andric // * Too-small integers, like 7, 70, and 99, will cause lower_bound() to return the D == 2 row. (If all we care
4760eae32dcSDimitry Andric //   about is whether D is less than 3, then it's okay to smash the D == 1 and D == 2 cases together.)
4770eae32dcSDimitry Andric // * Integers in [100, 999] will cause lower_bound() to return the D == 3 row, and so forth.
4780eae32dcSDimitry Andric // * Too-large integers, like 1'000'000 and above, will cause lower_bound() to return the end of the table. If we
4790eae32dcSDimitry Andric //   compute D from that index, this will be considered D == 7, which will activate any "greater than 6" logic.
4800eae32dcSDimitry Andric 
4810eae32dcSDimitry Andric // Floating-point is slightly more complicated.
4820eae32dcSDimitry Andric 
4830eae32dcSDimitry Andric // The ordinary lookup tables are for X within [-5, 38] for float, and [-5, 308] for double.
4840eae32dcSDimitry Andric // (-5 absorbs too-negative exponents, outside the P > X >= -4 criterion. 38 and 308 are the maximum exponents.)
4850eae32dcSDimitry Andric // Due to the P > X condition, we can use a subset of the table for X within [-5, P - 1], suitably clamped.
4860eae32dcSDimitry Andric 
4870eae32dcSDimitry Andric // When P is small, rounding can affect X. For example:
4880eae32dcSDimitry Andric // For P == 1, the largest double with X == 0 is: 9.4999999999999982236431605997495353221893310546875
4890eae32dcSDimitry Andric // For P == 2, the largest double with X == 0 is: 9.949999999999999289457264239899814128875732421875
4900eae32dcSDimitry Andric // For P == 3, the largest double with X == 0 is: 9.9949999999999992184029906638897955417633056640625
4910eae32dcSDimitry Andric 
4920eae32dcSDimitry Andric // Exponent adjustment is a concern for P within [1, 7] for float, and [1, 15] for double (determined via
4930eae32dcSDimitry Andric // brute force). While larger values of P still perform rounding, they can't trigger exponent adjustment.
4940eae32dcSDimitry Andric // This is because only values with repeated '9' digits can undergo exponent adjustment during rounding,
4950eae32dcSDimitry Andric // and floating-point granularity limits the number of consecutive '9' digits that can appear.
4960eae32dcSDimitry Andric 
4970eae32dcSDimitry Andric // So, we need special lookup tables for small values of P.
4980eae32dcSDimitry Andric // These tables have varying lengths due to the P > X >= -4 criterion. For example:
4990eae32dcSDimitry Andric // For P == 1, need table entries for X: -5, -4, -3, -2, -1, 0
5000eae32dcSDimitry Andric // For P == 2, need table entries for X: -5, -4, -3, -2, -1, 0, 1
5010eae32dcSDimitry Andric // For P == 3, need table entries for X: -5, -4, -3, -2, -1, 0, 1, 2
5020eae32dcSDimitry Andric // For P == 4, need table entries for X: -5, -4, -3, -2, -1, 0, 1, 2, 3
5030eae32dcSDimitry Andric 
5040eae32dcSDimitry Andric // We can concatenate these tables for compact storage, using triangular numbers to access them.
5050eae32dcSDimitry Andric // The table for P begins at index (P - 1) * (P + 10) / 2 with length P + 5.
5060eae32dcSDimitry Andric 
5070eae32dcSDimitry Andric // For both the ordinary and special lookup tables, after an index I is returned by lower_bound(), X is I - 5.
5080eae32dcSDimitry Andric 
5090eae32dcSDimitry Andric // We need to special-case the floating-point value 0.0, which is considered to have X == 0.
5100eae32dcSDimitry Andric // Otherwise, the lookup tables would consider it to have a highly negative X.
5110eae32dcSDimitry Andric 
5120eae32dcSDimitry Andric // Finally, because we're working with positive floating-point values,
5130eae32dcSDimitry Andric // representation comparisons behave identically to floating-point comparisons.
5140eae32dcSDimitry Andric 
5150eae32dcSDimitry Andric // The following code generated the lookup tables for the scientific exponent X. Don't remove this code.
5160eae32dcSDimitry Andric #if 0
5170eae32dcSDimitry Andric // cl /EHsc /nologo /W4 /MT /O2 /std:c++17 generate_tables.cpp && generate_tables
5180eae32dcSDimitry Andric 
5190eae32dcSDimitry Andric #include <algorithm>
5200eae32dcSDimitry Andric #include <assert.h>
5210eae32dcSDimitry Andric #include <charconv>
5220eae32dcSDimitry Andric #include <cmath>
5230eae32dcSDimitry Andric #include <limits>
5240eae32dcSDimitry Andric #include <map>
5250eae32dcSDimitry Andric #include <stdint.h>
5260eae32dcSDimitry Andric #include <stdio.h>
5270eae32dcSDimitry Andric #include <system_error>
5280eae32dcSDimitry Andric #include <type_traits>
5290eae32dcSDimitry Andric #include <vector>
5300eae32dcSDimitry Andric using namespace std;
5310eae32dcSDimitry Andric 
5320eae32dcSDimitry Andric template <typename UInt, typename Pred>
5330eae32dcSDimitry Andric [[nodiscard]] UInt uint_partition_point(UInt first, const UInt last, Pred pred) {
5340eae32dcSDimitry Andric     // Find the beginning of the false partition in [first, last).
5350eae32dcSDimitry Andric     // [first, last) is partitioned when all of the true values occur before all of the false values.
5360eae32dcSDimitry Andric 
5370eae32dcSDimitry Andric     static_assert(is_unsigned_v<UInt>);
5380eae32dcSDimitry Andric     assert(first <= last);
5390eae32dcSDimitry Andric 
5400eae32dcSDimitry Andric     for (UInt n = last - first; n > 0;) {
5410eae32dcSDimitry Andric         const UInt n2  = n / 2;
5420eae32dcSDimitry Andric         const UInt mid = first + n2;
5430eae32dcSDimitry Andric 
5440eae32dcSDimitry Andric         if (pred(mid)) {
5450eae32dcSDimitry Andric             first = mid + 1;
5460eae32dcSDimitry Andric             n     = n - n2 - 1;
5470eae32dcSDimitry Andric         } else {
5480eae32dcSDimitry Andric             n = n2;
5490eae32dcSDimitry Andric         }
5500eae32dcSDimitry Andric     }
5510eae32dcSDimitry Andric 
5520eae32dcSDimitry Andric     return first;
5530eae32dcSDimitry Andric }
5540eae32dcSDimitry Andric 
5550eae32dcSDimitry Andric template <typename Floating>
5560eae32dcSDimitry Andric [[nodiscard]] int scientific_exponent_X(const int P, const Floating flt) {
5570eae32dcSDimitry Andric     char buf[400]; // more than enough
5580eae32dcSDimitry Andric 
5590eae32dcSDimitry Andric     // C11 7.21.6.1 "The fprintf function"/8 performs trial formatting with scientific precision P - 1.
5600eae32dcSDimitry Andric     const auto to_result = to_chars(buf, end(buf), flt, chars_format::scientific, P - 1);
5610eae32dcSDimitry Andric     assert(to_result.ec == errc{});
5620eae32dcSDimitry Andric 
5630eae32dcSDimitry Andric     const char* exp_ptr = find(buf, to_result.ptr, 'e');
5640eae32dcSDimitry Andric     assert(exp_ptr != to_result.ptr);
5650eae32dcSDimitry Andric 
5660eae32dcSDimitry Andric     ++exp_ptr; // advance past 'e'
5670eae32dcSDimitry Andric 
5680eae32dcSDimitry Andric     if (*exp_ptr == '+') {
5690eae32dcSDimitry Andric         ++exp_ptr; // advance past '+' which from_chars() won't parse
5700eae32dcSDimitry Andric     }
5710eae32dcSDimitry Andric 
5720eae32dcSDimitry Andric     int X;
5730eae32dcSDimitry Andric     const auto from_result = from_chars(exp_ptr, to_result.ptr, X);
5740eae32dcSDimitry Andric     assert(from_result.ec == errc{});
5750eae32dcSDimitry Andric     return X;
5760eae32dcSDimitry Andric }
5770eae32dcSDimitry Andric 
5780eae32dcSDimitry Andric template <typename UInt>
5790eae32dcSDimitry Andric void print_table(const vector<UInt>& v, const char* const name) {
5800eae32dcSDimitry Andric     constexpr const char* UIntName = _IsSame<UInt, uint32_t>::value ? "uint32_t" : "uint64_t";
5810eae32dcSDimitry Andric 
5820eae32dcSDimitry Andric     printf("static constexpr %s %s[%zu] = {\n", UIntName, name, v.size());
5830eae32dcSDimitry Andric 
5840eae32dcSDimitry Andric     for (const auto& val : v) {
5850eae32dcSDimitry Andric         if constexpr (_IsSame<UInt, uint32_t>::value) {
5860eae32dcSDimitry Andric             printf("0x%08Xu,\n", val);
5870eae32dcSDimitry Andric         } else {
5880eae32dcSDimitry Andric             printf("0x%016llXu,\n", val);
5890eae32dcSDimitry Andric         }
5900eae32dcSDimitry Andric     }
5910eae32dcSDimitry Andric 
5920eae32dcSDimitry Andric     printf("};\n");
5930eae32dcSDimitry Andric }
5940eae32dcSDimitry Andric 
5950eae32dcSDimitry Andric enum class Mode { Tables, Tests };
5960eae32dcSDimitry Andric 
5970eae32dcSDimitry Andric template <typename Floating>
5980eae32dcSDimitry Andric void generate_tables(const Mode mode) {
5990eae32dcSDimitry Andric     using Limits = numeric_limits<Floating>;
6000eae32dcSDimitry Andric     using UInt   = conditional_t<_IsSame<Floating, float>::value, uint32_t, uint64_t>;
6010eae32dcSDimitry Andric 
6020eae32dcSDimitry Andric     map<int, map<int, UInt>> P_X_LargestValWithX;
6030eae32dcSDimitry Andric 
6040eae32dcSDimitry Andric     constexpr int MaxP = Limits::max_exponent10 + 1; // MaxP performs no rounding during trial formatting
6050eae32dcSDimitry Andric 
6060eae32dcSDimitry Andric     for (int P = 1; P <= MaxP; ++P) {
6070eae32dcSDimitry Andric         for (int X = -5; X < P; ++X) {
6080eae32dcSDimitry Andric             constexpr Floating first = static_cast<Floating>(9e-5); // well below 9.5e-5, otherwise arbitrary
6090eae32dcSDimitry Andric             constexpr Floating last  = Limits::infinity(); // one bit above Limits::max()
6100eae32dcSDimitry Andric 
6110eae32dcSDimitry Andric             const UInt val_beyond_X = uint_partition_point(reinterpret_cast<const UInt&>(first),
6120eae32dcSDimitry Andric                 reinterpret_cast<const UInt&>(last),
6130eae32dcSDimitry Andric                 [P, X](const UInt u) { return scientific_exponent_X(P, reinterpret_cast<const Floating&>(u)) <= X; });
6140eae32dcSDimitry Andric 
6150eae32dcSDimitry Andric             P_X_LargestValWithX[P][X] = val_beyond_X - 1;
6160eae32dcSDimitry Andric         }
6170eae32dcSDimitry Andric     }
6180eae32dcSDimitry Andric 
6190eae32dcSDimitry Andric     constexpr const char* FloatingName = _IsSame<Floating, float>::value ? "float" : "double";
6200eae32dcSDimitry Andric 
6210eae32dcSDimitry Andric     constexpr int MaxSpecialP = _IsSame<Floating, float>::value ? 7 : 15; // MaxSpecialP is affected by exponent adjustment
6220eae32dcSDimitry Andric 
6230eae32dcSDimitry Andric     if (mode == Mode::Tables) {
6240eae32dcSDimitry Andric         printf("template <>\n");
6250eae32dcSDimitry Andric         printf("struct _General_precision_tables<%s> {\n", FloatingName);
6260eae32dcSDimitry Andric 
6270eae32dcSDimitry Andric         printf("static constexpr int _Max_special_P = %d;\n", MaxSpecialP);
6280eae32dcSDimitry Andric 
6290eae32dcSDimitry Andric         vector<UInt> special;
6300eae32dcSDimitry Andric 
6310eae32dcSDimitry Andric         for (int P = 1; P <= MaxSpecialP; ++P) {
6320eae32dcSDimitry Andric             for (int X = -5; X < P; ++X) {
6330eae32dcSDimitry Andric                 const UInt val = P_X_LargestValWithX[P][X];
6340eae32dcSDimitry Andric                 special.push_back(val);
6350eae32dcSDimitry Andric             }
6360eae32dcSDimitry Andric         }
6370eae32dcSDimitry Andric 
6380eae32dcSDimitry Andric         print_table(special, "_Special_X_table");
6390eae32dcSDimitry Andric 
6400eae32dcSDimitry Andric         for (int P = MaxSpecialP + 1; P < MaxP; ++P) {
6410eae32dcSDimitry Andric             for (int X = -5; X < P; ++X) {
6420eae32dcSDimitry Andric                 const UInt val = P_X_LargestValWithX[P][X];
6430eae32dcSDimitry Andric                 assert(val == P_X_LargestValWithX[MaxP][X]);
6440eae32dcSDimitry Andric             }
6450eae32dcSDimitry Andric         }
6460eae32dcSDimitry Andric 
6470eae32dcSDimitry Andric         printf("static constexpr int _Max_P = %d;\n", MaxP);
6480eae32dcSDimitry Andric 
6490eae32dcSDimitry Andric         vector<UInt> ordinary;
6500eae32dcSDimitry Andric 
6510eae32dcSDimitry Andric         for (int X = -5; X < MaxP; ++X) {
6520eae32dcSDimitry Andric             const UInt val = P_X_LargestValWithX[MaxP][X];
6530eae32dcSDimitry Andric             ordinary.push_back(val);
6540eae32dcSDimitry Andric         }
6550eae32dcSDimitry Andric 
6560eae32dcSDimitry Andric         print_table(ordinary, "_Ordinary_X_table");
6570eae32dcSDimitry Andric 
6580eae32dcSDimitry Andric         printf("};\n");
6590eae32dcSDimitry Andric     } else {
6600eae32dcSDimitry Andric         printf("==========\n");
6610eae32dcSDimitry Andric         printf("Test cases for %s:\n", FloatingName);
6620eae32dcSDimitry Andric 
6630eae32dcSDimitry Andric         constexpr int Hexits         = _IsSame<Floating, float>::value ? 6 : 13;
6640eae32dcSDimitry Andric         constexpr const char* Suffix = _IsSame<Floating, float>::value ? "f" : "";
6650eae32dcSDimitry Andric 
6660eae32dcSDimitry Andric         for (int P = 1; P <= MaxP; ++P) {
6670eae32dcSDimitry Andric             for (int X = -5; X < P; ++X) {
6680eae32dcSDimitry Andric                 if (P <= MaxSpecialP || P == 25 || P == MaxP || X == P - 1) {
6690eae32dcSDimitry Andric                     const UInt val1   = P_X_LargestValWithX[P][X];
6700eae32dcSDimitry Andric                     const Floating f1 = reinterpret_cast<const Floating&>(val1);
6710eae32dcSDimitry Andric                     const UInt val2   = val1 + 1;
6720eae32dcSDimitry Andric                     const Floating f2 = reinterpret_cast<const Floating&>(val2);
6730eae32dcSDimitry Andric 
6740eae32dcSDimitry Andric                     printf("{%.*a%s, chars_format::general, %d, \"%.*g\"},\n", Hexits, f1, Suffix, P, P, f1);
6750eae32dcSDimitry Andric                     if (isfinite(f2)) {
6760eae32dcSDimitry Andric                         printf("{%.*a%s, chars_format::general, %d, \"%.*g\"},\n", Hexits, f2, Suffix, P, P, f2);
6770eae32dcSDimitry Andric                     }
6780eae32dcSDimitry Andric                 }
6790eae32dcSDimitry Andric             }
6800eae32dcSDimitry Andric         }
6810eae32dcSDimitry Andric     }
6820eae32dcSDimitry Andric }
6830eae32dcSDimitry Andric 
6840eae32dcSDimitry Andric int main() {
6850eae32dcSDimitry Andric     printf("template <class _Floating>\n");
6860eae32dcSDimitry Andric     printf("struct _General_precision_tables;\n");
6870eae32dcSDimitry Andric     generate_tables<float>(Mode::Tables);
6880eae32dcSDimitry Andric     generate_tables<double>(Mode::Tables);
6890eae32dcSDimitry Andric     generate_tables<float>(Mode::Tests);
6900eae32dcSDimitry Andric     generate_tables<double>(Mode::Tests);
6910eae32dcSDimitry Andric }
6920eae32dcSDimitry Andric #endif // 0
6930eae32dcSDimitry Andric 
6940eae32dcSDimitry Andric template <class _Floating>
6950eae32dcSDimitry Andric struct _General_precision_tables;
6960eae32dcSDimitry Andric 
6970eae32dcSDimitry Andric template <>
6980eae32dcSDimitry Andric struct _General_precision_tables<float> {
6990eae32dcSDimitry Andric     static constexpr int _Max_special_P = 7;
7000eae32dcSDimitry Andric 
7010eae32dcSDimitry Andric     static constexpr uint32_t _Special_X_table[63] = {0x38C73ABCu, 0x3A79096Bu, 0x3C1BA5E3u, 0x3DC28F5Cu, 0x3F733333u,
7020eae32dcSDimitry Andric         0x4117FFFFu, 0x38D0AAA7u, 0x3A826AA8u, 0x3C230553u, 0x3DCBC6A7u, 0x3F7EB851u, 0x411F3333u, 0x42C6FFFFu,
7030eae32dcSDimitry Andric         0x38D19C3Fu, 0x3A8301A7u, 0x3C23C211u, 0x3DCCB295u, 0x3F7FDF3Bu, 0x411FEB85u, 0x42C7E666u, 0x4479DFFFu,
7040eae32dcSDimitry Andric         0x38D1B468u, 0x3A8310C1u, 0x3C23D4F1u, 0x3DCCCA2Du, 0x3F7FFCB9u, 0x411FFDF3u, 0x42C7FD70u, 0x4479FCCCu,
7050eae32dcSDimitry Andric         0x461C3DFFu, 0x38D1B6D2u, 0x3A831243u, 0x3C23D6D4u, 0x3DCCCC89u, 0x3F7FFFACu, 0x411FFFCBu, 0x42C7FFBEu,
7060eae32dcSDimitry Andric         0x4479FFAEu, 0x461C3FCCu, 0x47C34FBFu, 0x38D1B710u, 0x3A83126Au, 0x3C23D704u, 0x3DCCCCC6u, 0x3F7FFFF7u,
7070eae32dcSDimitry Andric         0x411FFFFAu, 0x42C7FFF9u, 0x4479FFF7u, 0x461C3FFAu, 0x47C34FF9u, 0x497423F7u, 0x38D1B716u, 0x3A83126Eu,
7080eae32dcSDimitry Andric         0x3C23D709u, 0x3DCCCCCCu, 0x3F7FFFFFu, 0x411FFFFFu, 0x42C7FFFFu, 0x4479FFFFu, 0x461C3FFFu, 0x47C34FFFu,
7090eae32dcSDimitry Andric         0x497423FFu, 0x4B18967Fu};
7100eae32dcSDimitry Andric 
7110eae32dcSDimitry Andric     static constexpr int _Max_P = 39;
7120eae32dcSDimitry Andric 
7130eae32dcSDimitry Andric     static constexpr uint32_t _Ordinary_X_table[44] = {0x38D1B717u, 0x3A83126Eu, 0x3C23D70Au, 0x3DCCCCCCu, 0x3F7FFFFFu,
7140eae32dcSDimitry Andric         0x411FFFFFu, 0x42C7FFFFu, 0x4479FFFFu, 0x461C3FFFu, 0x47C34FFFu, 0x497423FFu, 0x4B18967Fu, 0x4CBEBC1Fu,
7150eae32dcSDimitry Andric         0x4E6E6B27u, 0x501502F8u, 0x51BA43B7u, 0x5368D4A5u, 0x551184E7u, 0x56B5E620u, 0x58635FA9u, 0x5A0E1BC9u,
7160eae32dcSDimitry Andric         0x5BB1A2BCu, 0x5D5E0B6Bu, 0x5F0AC723u, 0x60AD78EBu, 0x6258D726u, 0x64078678u, 0x65A96816u, 0x6753C21Bu,
7170eae32dcSDimitry Andric         0x69045951u, 0x6AA56FA5u, 0x6C4ECB8Fu, 0x6E013F39u, 0x6FA18F07u, 0x7149F2C9u, 0x72FC6F7Cu, 0x749DC5ADu,
7180eae32dcSDimitry Andric         0x76453719u, 0x77F684DFu, 0x799A130Bu, 0x7B4097CEu, 0x7CF0BDC2u, 0x7E967699u, 0x7F7FFFFFu};
7190eae32dcSDimitry Andric };
7200eae32dcSDimitry Andric 
7210eae32dcSDimitry Andric template <>
7220eae32dcSDimitry Andric struct _General_precision_tables<double> {
7230eae32dcSDimitry Andric     static constexpr int _Max_special_P = 15;
7240eae32dcSDimitry Andric 
7250eae32dcSDimitry Andric     static constexpr uint64_t _Special_X_table[195] = {0x3F18E757928E0C9Du, 0x3F4F212D77318FC5u, 0x3F8374BC6A7EF9DBu,
7260eae32dcSDimitry Andric         0x3FB851EB851EB851u, 0x3FEE666666666666u, 0x4022FFFFFFFFFFFFu, 0x3F1A1554FBDAD751u, 0x3F504D551D68C692u,
7270eae32dcSDimitry Andric         0x3F8460AA64C2F837u, 0x3FB978D4FDF3B645u, 0x3FEFD70A3D70A3D7u, 0x4023E66666666666u, 0x4058DFFFFFFFFFFFu,
7280eae32dcSDimitry Andric         0x3F1A3387ECC8EB96u, 0x3F506034F3FD933Eu, 0x3F84784230FCF80Du, 0x3FB99652BD3C3611u, 0x3FEFFBE76C8B4395u,
7290eae32dcSDimitry Andric         0x4023FD70A3D70A3Du, 0x4058FCCCCCCCCCCCu, 0x408F3BFFFFFFFFFFu, 0x3F1A368D04E0BA6Au, 0x3F506218230C7482u,
7300eae32dcSDimitry Andric         0x3F847A9E2BCF91A3u, 0x3FB99945B6C3760Bu, 0x3FEFFF972474538Eu, 0x4023FFBE76C8B439u, 0x4058FFAE147AE147u,
7310eae32dcSDimitry Andric         0x408F3F9999999999u, 0x40C387BFFFFFFFFFu, 0x3F1A36DA54164F19u, 0x3F506248748DF16Fu, 0x3F847ADA91B16DCBu,
7320eae32dcSDimitry Andric         0x3FB99991361DC93Eu, 0x3FEFFFF583A53B8Eu, 0x4023FFF972474538u, 0x4058FFF7CED91687u, 0x408F3FF5C28F5C28u,
7330eae32dcSDimitry Andric         0x40C387F999999999u, 0x40F869F7FFFFFFFFu, 0x3F1A36E20F35445Du, 0x3F50624D49814ABAu, 0x3F847AE09BE19D69u,
7340eae32dcSDimitry Andric         0x3FB99998C2DA04C3u, 0x3FEFFFFEF39085F4u, 0x4023FFFF583A53B8u, 0x4058FFFF2E48E8A7u, 0x408F3FFEF9DB22D0u,
7350eae32dcSDimitry Andric         0x40C387FF5C28F5C2u, 0x40F869FF33333333u, 0x412E847EFFFFFFFFu, 0x3F1A36E2D51EC34Bu, 0x3F50624DC5333A0Eu,
7360eae32dcSDimitry Andric         0x3F847AE136800892u, 0x3FB9999984200AB7u, 0x3FEFFFFFE5280D65u, 0x4023FFFFEF39085Fu, 0x4058FFFFEB074A77u,
7370eae32dcSDimitry Andric         0x408F3FFFE5C91D14u, 0x40C387FFEF9DB22Du, 0x40F869FFEB851EB8u, 0x412E847FE6666666u, 0x416312CFEFFFFFFFu,
7380eae32dcSDimitry Andric         0x3F1A36E2E8E94FFCu, 0x3F50624DD191D1FDu, 0x3F847AE145F6467Du, 0x3FB999999773D81Cu, 0x3FEFFFFFFD50CE23u,
7390eae32dcSDimitry Andric         0x4023FFFFFE5280D6u, 0x4058FFFFFDE7210Bu, 0x408F3FFFFD60E94Eu, 0x40C387FFFE5C91D1u, 0x40F869FFFDF3B645u,
7400eae32dcSDimitry Andric         0x412E847FFD70A3D7u, 0x416312CFFE666666u, 0x4197D783FDFFFFFFu, 0x3F1A36E2EAE3F7A7u, 0x3F50624DD2CE7AC8u,
7410eae32dcSDimitry Andric         0x3F847AE14782197Bu, 0x3FB9999999629FD9u, 0x3FEFFFFFFFBB47D0u, 0x4023FFFFFFD50CE2u, 0x4058FFFFFFCA501Au,
7420eae32dcSDimitry Andric         0x408F3FFFFFBCE421u, 0x40C387FFFFD60E94u, 0x40F869FFFFCB923Au, 0x412E847FFFBE76C8u, 0x416312CFFFD70A3Du,
7430eae32dcSDimitry Andric         0x4197D783FFCCCCCCu, 0x41CDCD64FFBFFFFFu, 0x3F1A36E2EB16A205u, 0x3F50624DD2EE2543u, 0x3F847AE147A9AE94u,
7440eae32dcSDimitry Andric         0x3FB9999999941A39u, 0x3FEFFFFFFFF920C8u, 0x4023FFFFFFFBB47Du, 0x4058FFFFFFFAA19Cu, 0x408F3FFFFFF94A03u,
7450eae32dcSDimitry Andric         0x40C387FFFFFBCE42u, 0x40F869FFFFFAC1D2u, 0x412E847FFFF97247u, 0x416312CFFFFBE76Cu, 0x4197D783FFFAE147u,
7460eae32dcSDimitry Andric         0x41CDCD64FFF99999u, 0x4202A05F1FFBFFFFu, 0x3F1A36E2EB1BB30Fu, 0x3F50624DD2F14FE9u, 0x3F847AE147ADA3E3u,
7470eae32dcSDimitry Andric         0x3FB9999999990CDCu, 0x3FEFFFFFFFFF5014u, 0x4023FFFFFFFF920Cu, 0x4058FFFFFFFF768Fu, 0x408F3FFFFFFF5433u,
7480eae32dcSDimitry Andric         0x40C387FFFFFF94A0u, 0x40F869FFFFFF79C8u, 0x412E847FFFFF583Au, 0x416312CFFFFF9724u, 0x4197D783FFFF7CEDu,
7490eae32dcSDimitry Andric         0x41CDCD64FFFF5C28u, 0x4202A05F1FFF9999u, 0x42374876E7FF7FFFu, 0x3F1A36E2EB1C34C3u, 0x3F50624DD2F1A0FAu,
7500eae32dcSDimitry Andric         0x3F847AE147AE0938u, 0x3FB9999999998B86u, 0x3FEFFFFFFFFFEE68u, 0x4023FFFFFFFFF501u, 0x4058FFFFFFFFF241u,
7510eae32dcSDimitry Andric         0x408F3FFFFFFFEED1u, 0x40C387FFFFFFF543u, 0x40F869FFFFFFF294u, 0x412E847FFFFFEF39u, 0x416312CFFFFFF583u,
7520eae32dcSDimitry Andric         0x4197D783FFFFF2E4u, 0x41CDCD64FFFFEF9Du, 0x4202A05F1FFFF5C2u, 0x42374876E7FFF333u, 0x426D1A94A1FFEFFFu,
7530eae32dcSDimitry Andric         0x3F1A36E2EB1C41BBu, 0x3F50624DD2F1A915u, 0x3F847AE147AE135Au, 0x3FB9999999999831u, 0x3FEFFFFFFFFFFE3Du,
7540eae32dcSDimitry Andric         0x4023FFFFFFFFFEE6u, 0x4058FFFFFFFFFEA0u, 0x408F3FFFFFFFFE48u, 0x40C387FFFFFFFEEDu, 0x40F869FFFFFFFEA8u,
7550eae32dcSDimitry Andric         0x412E847FFFFFFE52u, 0x416312CFFFFFFEF3u, 0x4197D783FFFFFEB0u, 0x41CDCD64FFFFFE5Cu, 0x4202A05F1FFFFEF9u,
7560eae32dcSDimitry Andric         0x42374876E7FFFEB8u, 0x426D1A94A1FFFE66u, 0x42A2309CE53FFEFFu, 0x3F1A36E2EB1C4307u, 0x3F50624DD2F1A9E4u,
7570eae32dcSDimitry Andric         0x3F847AE147AE145Eu, 0x3FB9999999999975u, 0x3FEFFFFFFFFFFFD2u, 0x4023FFFFFFFFFFE3u, 0x4058FFFFFFFFFFDCu,
7580eae32dcSDimitry Andric         0x408F3FFFFFFFFFD4u, 0x40C387FFFFFFFFE4u, 0x40F869FFFFFFFFDDu, 0x412E847FFFFFFFD5u, 0x416312CFFFFFFFE5u,
7590eae32dcSDimitry Andric         0x4197D783FFFFFFDEu, 0x41CDCD64FFFFFFD6u, 0x4202A05F1FFFFFE5u, 0x42374876E7FFFFDFu, 0x426D1A94A1FFFFD7u,
7600eae32dcSDimitry Andric         0x42A2309CE53FFFE6u, 0x42D6BCC41E8FFFDFu, 0x3F1A36E2EB1C4328u, 0x3F50624DD2F1A9F9u, 0x3F847AE147AE1477u,
7610eae32dcSDimitry Andric         0x3FB9999999999995u, 0x3FEFFFFFFFFFFFFBu, 0x4023FFFFFFFFFFFDu, 0x4058FFFFFFFFFFFCu, 0x408F3FFFFFFFFFFBu,
7620eae32dcSDimitry Andric         0x40C387FFFFFFFFFDu, 0x40F869FFFFFFFFFCu, 0x412E847FFFFFFFFBu, 0x416312CFFFFFFFFDu, 0x4197D783FFFFFFFCu,
7630eae32dcSDimitry Andric         0x41CDCD64FFFFFFFBu, 0x4202A05F1FFFFFFDu, 0x42374876E7FFFFFCu, 0x426D1A94A1FFFFFBu, 0x42A2309CE53FFFFDu,
7640eae32dcSDimitry Andric         0x42D6BCC41E8FFFFCu, 0x430C6BF52633FFFBu};
7650eae32dcSDimitry Andric 
7660eae32dcSDimitry Andric     static constexpr int _Max_P = 309;
7670eae32dcSDimitry Andric 
7680eae32dcSDimitry Andric     static constexpr uint64_t _Ordinary_X_table[314] = {0x3F1A36E2EB1C432Cu, 0x3F50624DD2F1A9FBu, 0x3F847AE147AE147Au,
7690eae32dcSDimitry Andric         0x3FB9999999999999u, 0x3FEFFFFFFFFFFFFFu, 0x4023FFFFFFFFFFFFu, 0x4058FFFFFFFFFFFFu, 0x408F3FFFFFFFFFFFu,
7700eae32dcSDimitry Andric         0x40C387FFFFFFFFFFu, 0x40F869FFFFFFFFFFu, 0x412E847FFFFFFFFFu, 0x416312CFFFFFFFFFu, 0x4197D783FFFFFFFFu,
7710eae32dcSDimitry Andric         0x41CDCD64FFFFFFFFu, 0x4202A05F1FFFFFFFu, 0x42374876E7FFFFFFu, 0x426D1A94A1FFFFFFu, 0x42A2309CE53FFFFFu,
7720eae32dcSDimitry Andric         0x42D6BCC41E8FFFFFu, 0x430C6BF52633FFFFu, 0x4341C37937E07FFFu, 0x4376345785D89FFFu, 0x43ABC16D674EC7FFu,
7730eae32dcSDimitry Andric         0x43E158E460913CFFu, 0x4415AF1D78B58C3Fu, 0x444B1AE4D6E2EF4Fu, 0x4480F0CF064DD591u, 0x44B52D02C7E14AF6u,
7740eae32dcSDimitry Andric         0x44EA784379D99DB4u, 0x45208B2A2C280290u, 0x4554ADF4B7320334u, 0x4589D971E4FE8401u, 0x45C027E72F1F1281u,
7750eae32dcSDimitry Andric         0x45F431E0FAE6D721u, 0x46293E5939A08CE9u, 0x465F8DEF8808B024u, 0x4693B8B5B5056E16u, 0x46C8A6E32246C99Cu,
7760eae32dcSDimitry Andric         0x46FED09BEAD87C03u, 0x4733426172C74D82u, 0x476812F9CF7920E2u, 0x479E17B84357691Bu, 0x47D2CED32A16A1B1u,
7770eae32dcSDimitry Andric         0x48078287F49C4A1Du, 0x483D6329F1C35CA4u, 0x48725DFA371A19E6u, 0x48A6F578C4E0A060u, 0x48DCB2D6F618C878u,
7780eae32dcSDimitry Andric         0x4911EFC659CF7D4Bu, 0x49466BB7F0435C9Eu, 0x497C06A5EC5433C6u, 0x49B18427B3B4A05Bu, 0x49E5E531A0A1C872u,
7790eae32dcSDimitry Andric         0x4A1B5E7E08CA3A8Fu, 0x4A511B0EC57E6499u, 0x4A8561D276DDFDC0u, 0x4ABABA4714957D30u, 0x4AF0B46C6CDD6E3Eu,
7800eae32dcSDimitry Andric         0x4B24E1878814C9CDu, 0x4B5A19E96A19FC40u, 0x4B905031E2503DA8u, 0x4BC4643E5AE44D12u, 0x4BF97D4DF19D6057u,
7810eae32dcSDimitry Andric         0x4C2FDCA16E04B86Du, 0x4C63E9E4E4C2F344u, 0x4C98E45E1DF3B015u, 0x4CCF1D75A5709C1Au, 0x4D03726987666190u,
7820eae32dcSDimitry Andric         0x4D384F03E93FF9F4u, 0x4D6E62C4E38FF872u, 0x4DA2FDBB0E39FB47u, 0x4DD7BD29D1C87A19u, 0x4E0DAC74463A989Fu,
7830eae32dcSDimitry Andric         0x4E428BC8ABE49F63u, 0x4E772EBAD6DDC73Cu, 0x4EACFA698C95390Bu, 0x4EE21C81F7DD43A7u, 0x4F16A3A275D49491u,
7840eae32dcSDimitry Andric         0x4F4C4C8B1349B9B5u, 0x4F81AFD6EC0E1411u, 0x4FB61BCCA7119915u, 0x4FEBA2BFD0D5FF5Bu, 0x502145B7E285BF98u,
7850eae32dcSDimitry Andric         0x50559725DB272F7Fu, 0x508AFCEF51F0FB5Eu, 0x50C0DE1593369D1Bu, 0x50F5159AF8044462u, 0x512A5B01B605557Au,
7860eae32dcSDimitry Andric         0x516078E111C3556Cu, 0x5194971956342AC7u, 0x51C9BCDFABC13579u, 0x5200160BCB58C16Cu, 0x52341B8EBE2EF1C7u,
7870eae32dcSDimitry Andric         0x526922726DBAAE39u, 0x529F6B0F092959C7u, 0x52D3A2E965B9D81Cu, 0x53088BA3BF284E23u, 0x533EAE8CAEF261ACu,
7880eae32dcSDimitry Andric         0x53732D17ED577D0Bu, 0x53A7F85DE8AD5C4Eu, 0x53DDF67562D8B362u, 0x5412BA095DC7701Du, 0x5447688BB5394C25u,
7890eae32dcSDimitry Andric         0x547D42AEA2879F2Eu, 0x54B249AD2594C37Cu, 0x54E6DC186EF9F45Cu, 0x551C931E8AB87173u, 0x5551DBF316B346E7u,
7900eae32dcSDimitry Andric         0x558652EFDC6018A1u, 0x55BBE7ABD3781ECAu, 0x55F170CB642B133Eu, 0x5625CCFE3D35D80Eu, 0x565B403DCC834E11u,
7910eae32dcSDimitry Andric         0x569108269FD210CBu, 0x56C54A3047C694FDu, 0x56FA9CBC59B83A3Du, 0x5730A1F5B8132466u, 0x5764CA732617ED7Fu,
7920eae32dcSDimitry Andric         0x5799FD0FEF9DE8DFu, 0x57D03E29F5C2B18Bu, 0x58044DB473335DEEu, 0x583961219000356Au, 0x586FB969F40042C5u,
7930eae32dcSDimitry Andric         0x58A3D3E2388029BBu, 0x58D8C8DAC6A0342Au, 0x590EFB1178484134u, 0x59435CEAEB2D28C0u, 0x59783425A5F872F1u,
7940eae32dcSDimitry Andric         0x59AE412F0F768FADu, 0x59E2E8BD69AA19CCu, 0x5A17A2ECC414A03Fu, 0x5A4D8BA7F519C84Fu, 0x5A827748F9301D31u,
7950eae32dcSDimitry Andric         0x5AB7151B377C247Eu, 0x5AECDA62055B2D9Du, 0x5B22087D4358FC82u, 0x5B568A9C942F3BA3u, 0x5B8C2D43B93B0A8Bu,
7960eae32dcSDimitry Andric         0x5BC19C4A53C4E697u, 0x5BF6035CE8B6203Du, 0x5C2B843422E3A84Cu, 0x5C6132A095CE492Fu, 0x5C957F48BB41DB7Bu,
7970eae32dcSDimitry Andric         0x5CCADF1AEA12525Au, 0x5D00CB70D24B7378u, 0x5D34FE4D06DE5056u, 0x5D6A3DE04895E46Cu, 0x5DA066AC2D5DAEC3u,
7980eae32dcSDimitry Andric         0x5DD4805738B51A74u, 0x5E09A06D06E26112u, 0x5E400444244D7CABu, 0x5E7405552D60DBD6u, 0x5EA906AA78B912CBu,
7990eae32dcSDimitry Andric         0x5EDF485516E7577Eu, 0x5F138D352E5096AFu, 0x5F48708279E4BC5Au, 0x5F7E8CA3185DEB71u, 0x5FB317E5EF3AB327u,
8000eae32dcSDimitry Andric         0x5FE7DDDF6B095FF0u, 0x601DD55745CBB7ECu, 0x6052A5568B9F52F4u, 0x60874EAC2E8727B1u, 0x60BD22573A28F19Du,
8010eae32dcSDimitry Andric         0x60F2357684599702u, 0x6126C2D4256FFCC2u, 0x615C73892ECBFBF3u, 0x6191C835BD3F7D78u, 0x61C63A432C8F5CD6u,
8020eae32dcSDimitry Andric         0x61FBC8D3F7B3340Bu, 0x62315D847AD00087u, 0x6265B4E5998400A9u, 0x629B221EFFE500D3u, 0x62D0F5535FEF2084u,
8030eae32dcSDimitry Andric         0x630532A837EAE8A5u, 0x633A7F5245E5A2CEu, 0x63708F936BAF85C1u, 0x63A4B378469B6731u, 0x63D9E056584240FDu,
8040eae32dcSDimitry Andric         0x64102C35F729689Eu, 0x6444374374F3C2C6u, 0x647945145230B377u, 0x64AF965966BCE055u, 0x64E3BDF7E0360C35u,
8050eae32dcSDimitry Andric         0x6518AD75D8438F43u, 0x654ED8D34E547313u, 0x6583478410F4C7ECu, 0x65B819651531F9E7u, 0x65EE1FBE5A7E7861u,
8060eae32dcSDimitry Andric         0x6622D3D6F88F0B3Cu, 0x665788CCB6B2CE0Cu, 0x668D6AFFE45F818Fu, 0x66C262DFEEBBB0F9u, 0x66F6FB97EA6A9D37u,
8070eae32dcSDimitry Andric         0x672CBA7DE5054485u, 0x6761F48EAF234AD3u, 0x679671B25AEC1D88u, 0x67CC0E1EF1A724EAu, 0x680188D357087712u,
8080eae32dcSDimitry Andric         0x6835EB082CCA94D7u, 0x686B65CA37FD3A0Du, 0x68A11F9E62FE4448u, 0x68D56785FBBDD55Au, 0x690AC1677AAD4AB0u,
8090eae32dcSDimitry Andric         0x6940B8E0ACAC4EAEu, 0x6974E718D7D7625Au, 0x69AA20DF0DCD3AF0u, 0x69E0548B68A044D6u, 0x6A1469AE42C8560Cu,
8100eae32dcSDimitry Andric         0x6A498419D37A6B8Fu, 0x6A7FE52048590672u, 0x6AB3EF342D37A407u, 0x6AE8EB0138858D09u, 0x6B1F25C186A6F04Cu,
8110eae32dcSDimitry Andric         0x6B537798F428562Fu, 0x6B88557F31326BBBu, 0x6BBE6ADEFD7F06AAu, 0x6BF302CB5E6F642Au, 0x6C27C37E360B3D35u,
8120eae32dcSDimitry Andric         0x6C5DB45DC38E0C82u, 0x6C9290BA9A38C7D1u, 0x6CC734E940C6F9C5u, 0x6CFD022390F8B837u, 0x6D3221563A9B7322u,
8130eae32dcSDimitry Andric         0x6D66A9ABC9424FEBu, 0x6D9C5416BB92E3E6u, 0x6DD1B48E353BCE6Fu, 0x6E0621B1C28AC20Bu, 0x6E3BAA1E332D728Eu,
8140eae32dcSDimitry Andric         0x6E714A52DFFC6799u, 0x6EA59CE797FB817Fu, 0x6EDB04217DFA61DFu, 0x6F10E294EEBC7D2Bu, 0x6F451B3A2A6B9C76u,
8150eae32dcSDimitry Andric         0x6F7A6208B5068394u, 0x6FB07D457124123Cu, 0x6FE49C96CD6D16CBu, 0x7019C3BC80C85C7Eu, 0x70501A55D07D39CFu,
8160eae32dcSDimitry Andric         0x708420EB449C8842u, 0x70B9292615C3AA53u, 0x70EF736F9B3494E8u, 0x7123A825C100DD11u, 0x7158922F31411455u,
8170eae32dcSDimitry Andric         0x718EB6BAFD91596Bu, 0x71C33234DE7AD7E2u, 0x71F7FEC216198DDBu, 0x722DFE729B9FF152u, 0x7262BF07A143F6D3u,
8180eae32dcSDimitry Andric         0x72976EC98994F488u, 0x72CD4A7BEBFA31AAu, 0x73024E8D737C5F0Au, 0x7336E230D05B76CDu, 0x736C9ABD04725480u,
8190eae32dcSDimitry Andric         0x73A1E0B622C774D0u, 0x73D658E3AB795204u, 0x740BEF1C9657A685u, 0x74417571DDF6C813u, 0x7475D2CE55747A18u,
8200eae32dcSDimitry Andric         0x74AB4781EAD1989Eu, 0x74E10CB132C2FF63u, 0x75154FDD7F73BF3Bu, 0x754AA3D4DF50AF0Au, 0x7580A6650B926D66u,
8210eae32dcSDimitry Andric         0x75B4CFFE4E7708C0u, 0x75EA03FDE214CAF0u, 0x7620427EAD4CFED6u, 0x7654531E58A03E8Bu, 0x768967E5EEC84E2Eu,
8220eae32dcSDimitry Andric         0x76BFC1DF6A7A61BAu, 0x76F3D92BA28C7D14u, 0x7728CF768B2F9C59u, 0x775F03542DFB8370u, 0x779362149CBD3226u,
8230eae32dcSDimitry Andric         0x77C83A99C3EC7EAFu, 0x77FE494034E79E5Bu, 0x7832EDC82110C2F9u, 0x7867A93A2954F3B7u, 0x789D9388B3AA30A5u,
8240eae32dcSDimitry Andric         0x78D27C35704A5E67u, 0x79071B42CC5CF601u, 0x793CE2137F743381u, 0x79720D4C2FA8A030u, 0x79A6909F3B92C83Du,
8250eae32dcSDimitry Andric         0x79DC34C70A777A4Cu, 0x7A11A0FC668AAC6Fu, 0x7A46093B802D578Bu, 0x7A7B8B8A6038AD6Eu, 0x7AB137367C236C65u,
8260eae32dcSDimitry Andric         0x7AE585041B2C477Eu, 0x7B1AE64521F7595Eu, 0x7B50CFEB353A97DAu, 0x7B8503E602893DD1u, 0x7BBA44DF832B8D45u,
8270eae32dcSDimitry Andric         0x7BF06B0BB1FB384Bu, 0x7C2485CE9E7A065Eu, 0x7C59A742461887F6u, 0x7C9008896BCF54F9u, 0x7CC40AABC6C32A38u,
8280eae32dcSDimitry Andric         0x7CF90D56B873F4C6u, 0x7D2F50AC6690F1F8u, 0x7D63926BC01A973Bu, 0x7D987706B0213D09u, 0x7DCE94C85C298C4Cu,
8290eae32dcSDimitry Andric         0x7E031CFD3999F7AFu, 0x7E37E43C8800759Bu, 0x7E6DDD4BAA009302u, 0x7EA2AA4F4A405BE1u, 0x7ED754E31CD072D9u,
8300eae32dcSDimitry Andric         0x7F0D2A1BE4048F90u, 0x7F423A516E82D9BAu, 0x7F76C8E5CA239028u, 0x7FAC7B1F3CAC7433u, 0x7FE1CCF385EBC89Fu,
8310eae32dcSDimitry Andric         0x7FEFFFFFFFFFFFFFu};
8320eae32dcSDimitry Andric };
8330eae32dcSDimitry Andric 
8340eae32dcSDimitry Andric template <class _Floating>
8350eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
8360eae32dcSDimitry Andric to_chars_result _Floating_to_chars_general_precision(
8370eae32dcSDimitry Andric     char* _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
8380eae32dcSDimitry Andric 
8390eae32dcSDimitry Andric     using _Traits    = _Floating_type_traits<_Floating>;
8400eae32dcSDimitry Andric     using _Uint_type = typename _Traits::_Uint_type;
8410eae32dcSDimitry Andric 
8425f757f3fSDimitry Andric     const _Uint_type _Uint_value = std::bit_cast<_Uint_type>(_Value);
8430eae32dcSDimitry Andric 
8440eae32dcSDimitry Andric     if (_Uint_value == 0) { // zero detected; write "0" and return; _Precision is irrelevant due to zero-trimming
8450eae32dcSDimitry Andric         if (_First == _Last) {
8460eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
8470eae32dcSDimitry Andric         }
8480eae32dcSDimitry Andric 
8490eae32dcSDimitry Andric         *_First++ = '0';
8500eae32dcSDimitry Andric 
8510eae32dcSDimitry Andric         return {_First, errc{}};
8520eae32dcSDimitry Andric     }
8530eae32dcSDimitry Andric 
8540eae32dcSDimitry Andric     // C11 7.21.6.1 "The fprintf function"/5:
8550eae32dcSDimitry Andric     // "A negative precision argument is taken as if the precision were omitted."
8560eae32dcSDimitry Andric     // /8: "g,G [...] Let P equal the precision if nonzero, 6 if the precision is omitted,
8570eae32dcSDimitry Andric     // or 1 if the precision is zero."
8580eae32dcSDimitry Andric 
8590eae32dcSDimitry Andric     // Performance note: It's possible to rewrite this for branchless codegen,
8600eae32dcSDimitry Andric     // but profiling will be necessary to determine whether that's faster.
8610eae32dcSDimitry Andric     if (_Precision < 0) {
8620eae32dcSDimitry Andric         _Precision = 6;
8630eae32dcSDimitry Andric     } else if (_Precision == 0) {
8640eae32dcSDimitry Andric         _Precision = 1;
8650eae32dcSDimitry Andric     } else if (_Precision < 1'000'000) {
8660eae32dcSDimitry Andric         // _Precision is ok.
8670eae32dcSDimitry Andric     } else {
8680eae32dcSDimitry Andric         // Avoid integer overflow.
8690eae32dcSDimitry Andric         // Due to general notation's zero-trimming behavior, we can simply clamp _Precision.
8700eae32dcSDimitry Andric         // This is further clamped below.
8710eae32dcSDimitry Andric         _Precision = 1'000'000;
8720eae32dcSDimitry Andric     }
8730eae32dcSDimitry Andric 
8740eae32dcSDimitry Andric     // _Precision is now the Standard's P.
8750eae32dcSDimitry Andric 
8760eae32dcSDimitry Andric     // /8: "Then, if a conversion with style E would have an exponent of X:
8770eae32dcSDimitry Andric     // - if P > X >= -4, the conversion is with style f (or F) and precision P - (X + 1).
8780eae32dcSDimitry Andric     // - otherwise, the conversion is with style e (or E) and precision P - 1."
8790eae32dcSDimitry Andric 
8800eae32dcSDimitry Andric     // /8: "Finally, [...] any trailing zeros are removed from the fractional portion of the result
8810eae32dcSDimitry Andric     // and the decimal-point character is removed if there is no fractional portion remaining."
8820eae32dcSDimitry Andric 
8830eae32dcSDimitry Andric     using _Tables = _General_precision_tables<_Floating>;
8840eae32dcSDimitry Andric 
8850eae32dcSDimitry Andric     const _Uint_type* _Table_begin;
8860eae32dcSDimitry Andric     const _Uint_type* _Table_end;
8870eae32dcSDimitry Andric 
8880eae32dcSDimitry Andric     if (_Precision <= _Tables::_Max_special_P) {
8890eae32dcSDimitry Andric         _Table_begin = _Tables::_Special_X_table + (_Precision - 1) * (_Precision + 10) / 2;
8900eae32dcSDimitry Andric         _Table_end   = _Table_begin + _Precision + 5;
8910eae32dcSDimitry Andric     } else {
8920eae32dcSDimitry Andric         _Table_begin = _Tables::_Ordinary_X_table;
8935f757f3fSDimitry Andric         _Table_end   = _Table_begin + std::min(_Precision, _Tables::_Max_P) + 5;
8940eae32dcSDimitry Andric     }
8950eae32dcSDimitry Andric 
8960eae32dcSDimitry Andric     // Profiling indicates that linear search is faster than binary search for small tables.
8970eae32dcSDimitry Andric     // Performance note: lambda captures may have a small performance cost.
8980eae32dcSDimitry Andric     const _Uint_type* const _Table_lower_bound = [=] {
8990eae32dcSDimitry Andric         if constexpr (!_IsSame<_Floating, float>::value) {
9000eae32dcSDimitry Andric             if (_Precision > 155) { // threshold determined via profiling
9015f757f3fSDimitry Andric                 return std::lower_bound(_Table_begin, _Table_end, _Uint_value, less{});
9020eae32dcSDimitry Andric             }
9030eae32dcSDimitry Andric         }
9040eae32dcSDimitry Andric 
9055f757f3fSDimitry Andric         return std::find_if(_Table_begin, _Table_end, [=](const _Uint_type _Elem) { return _Uint_value <= _Elem; });
9060eae32dcSDimitry Andric     }();
9070eae32dcSDimitry Andric 
9080eae32dcSDimitry Andric     const ptrdiff_t _Table_index     = _Table_lower_bound - _Table_begin;
9090eae32dcSDimitry Andric     const int _Scientific_exponent_X = static_cast<int>(_Table_index - 5);
9100eae32dcSDimitry Andric     const bool _Use_fixed_notation   = _Precision > _Scientific_exponent_X && _Scientific_exponent_X >= -4;
9110eae32dcSDimitry Andric 
9120eae32dcSDimitry Andric     // Performance note: it might (or might not) be faster to modify Ryu Printf to perform zero-trimming.
9130eae32dcSDimitry Andric     // Such modifications would involve a fairly complicated state machine (notably, both '0' and '9' digits would
9140eae32dcSDimitry Andric     // need to be buffered, due to rounding), and that would have performance costs due to increased branching.
9150eae32dcSDimitry Andric     // Here, we're using a simpler approach: writing into a local buffer, manually zero-trimming, and then copying into
9160eae32dcSDimitry Andric     // the output range. The necessary buffer size is reasonably small, the zero-trimming logic is simple and fast,
9170eae32dcSDimitry Andric     // and the final copying is also fast.
9180eae32dcSDimitry Andric 
9190eae32dcSDimitry Andric     constexpr int _Max_output_length =
9200eae32dcSDimitry Andric         _IsSame<_Floating, float>::value ? 117 : 773; // cases: 0x1.fffffep-126f and 0x1.fffffffffffffp-1022
9210eae32dcSDimitry Andric     constexpr int _Max_fixed_precision =
9220eae32dcSDimitry Andric         _IsSame<_Floating, float>::value ? 37 : 66; // cases: 0x1.fffffep-14f and 0x1.fffffffffffffp-14
9230eae32dcSDimitry Andric     constexpr int _Max_scientific_precision =
9240eae32dcSDimitry Andric         _IsSame<_Floating, float>::value ? 111 : 766; // cases: 0x1.fffffep-126f and 0x1.fffffffffffffp-1022
9250eae32dcSDimitry Andric 
9260eae32dcSDimitry Andric     // Note that _Max_output_length is determined by scientific notation and is more than enough for fixed notation.
9270eae32dcSDimitry Andric     // 0x1.fffffep+127f is 39 digits, plus 1 for '.', plus _Max_fixed_precision for '0' digits, equals 77.
9280eae32dcSDimitry Andric     // 0x1.fffffffffffffp+1023 is 309 digits, plus 1 for '.', plus _Max_fixed_precision for '0' digits, equals 376.
9290eae32dcSDimitry Andric 
9300eae32dcSDimitry Andric     char _Buffer[_Max_output_length];
9310eae32dcSDimitry Andric     const char* const _Significand_first = _Buffer; // e.g. "1.234"
9320eae32dcSDimitry Andric     const char* _Significand_last        = nullptr;
9330eae32dcSDimitry Andric     const char* _Exponent_first          = nullptr; // e.g. "e-05"
9340eae32dcSDimitry Andric     const char* _Exponent_last           = nullptr;
9350eae32dcSDimitry Andric     int _Effective_precision; // number of digits printed after the decimal point, before trimming
9360eae32dcSDimitry Andric 
9370eae32dcSDimitry Andric     // Write into the local buffer.
9380eae32dcSDimitry Andric     // Clamping _Effective_precision allows _Buffer to be as small as possible, and increases efficiency.
9390eae32dcSDimitry Andric     if (_Use_fixed_notation) {
9405f757f3fSDimitry Andric         _Effective_precision = std::min(_Precision - (_Scientific_exponent_X + 1), _Max_fixed_precision);
9410eae32dcSDimitry Andric         const to_chars_result _Buf_result =
9425f757f3fSDimitry Andric             _Floating_to_chars_fixed_precision(_Buffer, std::end(_Buffer), _Value, _Effective_precision);
9431db9f3b2SDimitry Andric         _LIBCPP_ASSERT_INTERNAL(_Buf_result.ec == errc{}, "");
9440eae32dcSDimitry Andric         _Significand_last = _Buf_result.ptr;
9450eae32dcSDimitry Andric     } else {
9465f757f3fSDimitry Andric         _Effective_precision = std::min(_Precision - 1, _Max_scientific_precision);
9470eae32dcSDimitry Andric         const to_chars_result _Buf_result =
9485f757f3fSDimitry Andric             _Floating_to_chars_scientific_precision(_Buffer, std::end(_Buffer), _Value, _Effective_precision);
9491db9f3b2SDimitry Andric         _LIBCPP_ASSERT_INTERNAL(_Buf_result.ec == errc{}, "");
9505f757f3fSDimitry Andric         _Significand_last = std::find(_Buffer, _Buf_result.ptr, 'e');
9510eae32dcSDimitry Andric         _Exponent_first   = _Significand_last;
9520eae32dcSDimitry Andric         _Exponent_last    = _Buf_result.ptr;
9530eae32dcSDimitry Andric     }
9540eae32dcSDimitry Andric 
9550eae32dcSDimitry Andric     // If we printed a decimal point followed by digits, perform zero-trimming.
9560eae32dcSDimitry Andric     if (_Effective_precision > 0) {
9570eae32dcSDimitry Andric         while (_Significand_last[-1] == '0') { // will stop at '.' or a nonzero digit
9580eae32dcSDimitry Andric             --_Significand_last;
9590eae32dcSDimitry Andric         }
9600eae32dcSDimitry Andric 
9610eae32dcSDimitry Andric         if (_Significand_last[-1] == '.') {
9620eae32dcSDimitry Andric             --_Significand_last;
9630eae32dcSDimitry Andric         }
9640eae32dcSDimitry Andric     }
9650eae32dcSDimitry Andric 
9660eae32dcSDimitry Andric     // Copy the significand to the output range.
9670eae32dcSDimitry Andric     const ptrdiff_t _Significand_distance = _Significand_last - _Significand_first;
9680eae32dcSDimitry Andric     if (_Last - _First < _Significand_distance) {
9690eae32dcSDimitry Andric         return {_Last, errc::value_too_large};
9700eae32dcSDimitry Andric     }
9715f757f3fSDimitry Andric     std::memcpy(_First, _Significand_first, static_cast<size_t>(_Significand_distance));
9720eae32dcSDimitry Andric     _First += _Significand_distance;
9730eae32dcSDimitry Andric 
9740eae32dcSDimitry Andric     // Copy the exponent to the output range.
9750eae32dcSDimitry Andric     if (!_Use_fixed_notation) {
9760eae32dcSDimitry Andric         const ptrdiff_t _Exponent_distance = _Exponent_last - _Exponent_first;
9770eae32dcSDimitry Andric         if (_Last - _First < _Exponent_distance) {
9780eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
9790eae32dcSDimitry Andric         }
9805f757f3fSDimitry Andric         std::memcpy(_First, _Exponent_first, static_cast<size_t>(_Exponent_distance));
9810eae32dcSDimitry Andric         _First += _Exponent_distance;
9820eae32dcSDimitry Andric     }
9830eae32dcSDimitry Andric 
9840eae32dcSDimitry Andric     return {_First, errc{}};
9850eae32dcSDimitry Andric }
9860eae32dcSDimitry Andric 
9870eae32dcSDimitry Andric enum class _Floating_to_chars_overload { _Plain, _Format_only, _Format_precision };
9880eae32dcSDimitry Andric 
9890eae32dcSDimitry Andric template <_Floating_to_chars_overload _Overload, class _Floating>
9900eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
9910eae32dcSDimitry Andric to_chars_result _Floating_to_chars(
9920eae32dcSDimitry Andric     char* _First, char* const _Last, _Floating _Value, const chars_format _Fmt, const int _Precision) noexcept {
9930eae32dcSDimitry Andric 
9940eae32dcSDimitry Andric     if constexpr (_Overload == _Floating_to_chars_overload::_Plain) {
9951db9f3b2SDimitry Andric         _LIBCPP_ASSERT_INTERNAL(_Fmt == chars_format{}, ""); // plain overload must pass chars_format{} internally
9960eae32dcSDimitry Andric     } else {
997*7a6dacacSDimitry Andric         _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(_Fmt == chars_format::general || _Fmt == chars_format::scientific
99806c3fb27SDimitry Andric                          || _Fmt == chars_format::fixed || _Fmt == chars_format::hex,
9990eae32dcSDimitry Andric             "invalid format in to_chars()");
10000eae32dcSDimitry Andric     }
10010eae32dcSDimitry Andric 
10020eae32dcSDimitry Andric     using _Traits    = _Floating_type_traits<_Floating>;
10030eae32dcSDimitry Andric     using _Uint_type = typename _Traits::_Uint_type;
10040eae32dcSDimitry Andric 
10055f757f3fSDimitry Andric     _Uint_type _Uint_value = std::bit_cast<_Uint_type>(_Value);
10060eae32dcSDimitry Andric 
10070eae32dcSDimitry Andric     const bool _Was_negative = (_Uint_value & _Traits::_Shifted_sign_mask) != 0;
10080eae32dcSDimitry Andric 
10090eae32dcSDimitry Andric     if (_Was_negative) { // sign bit detected; write minus sign and clear sign bit
10100eae32dcSDimitry Andric         if (_First == _Last) {
10110eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
10120eae32dcSDimitry Andric         }
10130eae32dcSDimitry Andric 
10140eae32dcSDimitry Andric         *_First++ = '-';
10150eae32dcSDimitry Andric 
10160eae32dcSDimitry Andric         _Uint_value &= ~_Traits::_Shifted_sign_mask;
10175f757f3fSDimitry Andric         _Value = std::bit_cast<_Floating>(_Uint_value);
10180eae32dcSDimitry Andric     }
10190eae32dcSDimitry Andric 
10200eae32dcSDimitry Andric     if ((_Uint_value & _Traits::_Shifted_exponent_mask) == _Traits::_Shifted_exponent_mask) {
10210eae32dcSDimitry Andric         // inf/nan detected; write appropriate string and return
10220eae32dcSDimitry Andric         const char* _Str;
10230eae32dcSDimitry Andric         size_t _Len;
10240eae32dcSDimitry Andric 
10250eae32dcSDimitry Andric         const _Uint_type _Mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
10260eae32dcSDimitry Andric 
10270eae32dcSDimitry Andric         if (_Mantissa == 0) {
10280eae32dcSDimitry Andric             _Str = "inf";
10290eae32dcSDimitry Andric             _Len = 3;
10300eae32dcSDimitry Andric         } else if (_Was_negative && _Mantissa == _Traits::_Special_nan_mantissa_mask) {
10310eae32dcSDimitry Andric             // When a NaN value has the sign bit set, the quiet bit set, and all other mantissa bits cleared,
10320eae32dcSDimitry Andric             // the UCRT interprets it to mean "indeterminate", and indicates this by printing "-nan(ind)".
10330eae32dcSDimitry Andric             _Str = "nan(ind)";
10340eae32dcSDimitry Andric             _Len = 8;
10350eae32dcSDimitry Andric         } else if ((_Mantissa & _Traits::_Special_nan_mantissa_mask) != 0) {
10360eae32dcSDimitry Andric             _Str = "nan";
10370eae32dcSDimitry Andric             _Len = 3;
10380eae32dcSDimitry Andric         } else {
10390eae32dcSDimitry Andric             _Str = "nan(snan)";
10400eae32dcSDimitry Andric             _Len = 9;
10410eae32dcSDimitry Andric         }
10420eae32dcSDimitry Andric 
10430eae32dcSDimitry Andric         if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
10440eae32dcSDimitry Andric             return {_Last, errc::value_too_large};
10450eae32dcSDimitry Andric         }
10460eae32dcSDimitry Andric 
10475f757f3fSDimitry Andric         std::memcpy(_First, _Str, _Len);
10480eae32dcSDimitry Andric 
10490eae32dcSDimitry Andric         return {_First + _Len, errc{}};
10500eae32dcSDimitry Andric     }
10510eae32dcSDimitry Andric 
10520eae32dcSDimitry Andric     if constexpr (_Overload == _Floating_to_chars_overload::_Plain) {
10530eae32dcSDimitry Andric         return _Floating_to_chars_ryu(_First, _Last, _Value, chars_format{});
10540eae32dcSDimitry Andric     } else if constexpr (_Overload == _Floating_to_chars_overload::_Format_only) {
10550eae32dcSDimitry Andric         if (_Fmt == chars_format::hex) {
10560eae32dcSDimitry Andric             return _Floating_to_chars_hex_shortest(_First, _Last, _Value);
10570eae32dcSDimitry Andric         }
10580eae32dcSDimitry Andric 
10590eae32dcSDimitry Andric         return _Floating_to_chars_ryu(_First, _Last, _Value, _Fmt);
10600eae32dcSDimitry Andric     } else if constexpr (_Overload == _Floating_to_chars_overload::_Format_precision) {
10610eae32dcSDimitry Andric         switch (_Fmt) {
10620eae32dcSDimitry Andric         case chars_format::scientific:
10630eae32dcSDimitry Andric             return _Floating_to_chars_scientific_precision(_First, _Last, _Value, _Precision);
10640eae32dcSDimitry Andric         case chars_format::fixed:
10650eae32dcSDimitry Andric             return _Floating_to_chars_fixed_precision(_First, _Last, _Value, _Precision);
10660eae32dcSDimitry Andric         case chars_format::general:
10670eae32dcSDimitry Andric             return _Floating_to_chars_general_precision(_First, _Last, _Value, _Precision);
10680eae32dcSDimitry Andric         case chars_format::hex:
10690eae32dcSDimitry Andric         default: // avoid MSVC warning C4715: not all control paths return a value
10700eae32dcSDimitry Andric             return _Floating_to_chars_hex_precision(_First, _Last, _Value, _Precision);
10710eae32dcSDimitry Andric         }
10720eae32dcSDimitry Andric     }
10730eae32dcSDimitry Andric }
10740eae32dcSDimitry Andric 
10750eae32dcSDimitry Andric // clang-format on
10760eae32dcSDimitry Andric 
10770eae32dcSDimitry Andric _LIBCPP_END_NAMESPACE_STD
10780eae32dcSDimitry Andric 
10790eae32dcSDimitry Andric #endif // _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
1080