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