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 // Copyright 2018 Ulf Adams 130eae32dcSDimitry Andric // Copyright (c) Microsoft Corporation. All rights reserved. 140eae32dcSDimitry Andric 150eae32dcSDimitry Andric // Boost Software License - Version 1.0 - August 17th, 2003 160eae32dcSDimitry Andric 170eae32dcSDimitry Andric // Permission is hereby granted, free of charge, to any person or organization 180eae32dcSDimitry Andric // obtaining a copy of the software and accompanying documentation covered by 190eae32dcSDimitry Andric // this license (the "Software") to use, reproduce, display, distribute, 200eae32dcSDimitry Andric // execute, and transmit the Software, and to prepare derivative works of the 210eae32dcSDimitry Andric // Software, and to permit third-parties to whom the Software is furnished to 220eae32dcSDimitry Andric // do so, all subject to the following: 230eae32dcSDimitry Andric 240eae32dcSDimitry Andric // The copyright notices in the Software and this entire statement, including 250eae32dcSDimitry Andric // the above license grant, this restriction and the following disclaimer, 260eae32dcSDimitry Andric // must be included in all copies of the Software, in whole or in part, and 270eae32dcSDimitry Andric // all derivative works of the Software, unless such copies or derivative 280eae32dcSDimitry Andric // works are solely in the form of machine-executable object code generated by 290eae32dcSDimitry Andric // a source language processor. 300eae32dcSDimitry Andric 310eae32dcSDimitry Andric // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 320eae32dcSDimitry Andric // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 330eae32dcSDimitry Andric // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 340eae32dcSDimitry Andric // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 350eae32dcSDimitry Andric // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 360eae32dcSDimitry Andric // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 370eae32dcSDimitry Andric // DEALINGS IN THE SOFTWARE. 380eae32dcSDimitry Andric 390eae32dcSDimitry Andric // Avoid formatting to keep the changes with the original code minimal. 400eae32dcSDimitry Andric // clang-format off 410eae32dcSDimitry Andric 4281ad6265SDimitry Andric #include <__assert> 4381ad6265SDimitry Andric #include <__config> 4481ad6265SDimitry Andric #include <charconv> 4581ad6265SDimitry Andric #include <cstring> 460eae32dcSDimitry Andric 470eae32dcSDimitry Andric #include "include/ryu/common.h" 480eae32dcSDimitry Andric #include "include/ryu/d2fixed.h" 490eae32dcSDimitry Andric #include "include/ryu/d2fixed_full_table.h" 500eae32dcSDimitry Andric #include "include/ryu/d2s.h" 510eae32dcSDimitry Andric #include "include/ryu/d2s_intrinsics.h" 520eae32dcSDimitry Andric #include "include/ryu/digit_table.h" 530eae32dcSDimitry Andric 540eae32dcSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 550eae32dcSDimitry Andric 560eae32dcSDimitry Andric inline constexpr int __POW10_ADDITIONAL_BITS = 120; 570eae32dcSDimitry Andric 580eae32dcSDimitry Andric #ifdef _LIBCPP_INTRINSIC128 590eae32dcSDimitry Andric // Returns the low 64 bits of the high 128 bits of the 256-bit product of a and b. 600eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __umul256_hi128_lo64( 610eae32dcSDimitry Andric const uint64_t __aHi, const uint64_t __aLo, const uint64_t __bHi, const uint64_t __bLo) { 620eae32dcSDimitry Andric uint64_t __b00Hi; 630eae32dcSDimitry Andric const uint64_t __b00Lo = __ryu_umul128(__aLo, __bLo, &__b00Hi); 640eae32dcSDimitry Andric uint64_t __b01Hi; 650eae32dcSDimitry Andric const uint64_t __b01Lo = __ryu_umul128(__aLo, __bHi, &__b01Hi); 660eae32dcSDimitry Andric uint64_t __b10Hi; 670eae32dcSDimitry Andric const uint64_t __b10Lo = __ryu_umul128(__aHi, __bLo, &__b10Hi); 680eae32dcSDimitry Andric uint64_t __b11Hi; 690eae32dcSDimitry Andric const uint64_t __b11Lo = __ryu_umul128(__aHi, __bHi, &__b11Hi); 700eae32dcSDimitry Andric (void) __b00Lo; // unused 710eae32dcSDimitry Andric (void) __b11Hi; // unused 720eae32dcSDimitry Andric const uint64_t __temp1Lo = __b10Lo + __b00Hi; 730eae32dcSDimitry Andric const uint64_t __temp1Hi = __b10Hi + (__temp1Lo < __b10Lo); 740eae32dcSDimitry Andric const uint64_t __temp2Lo = __b01Lo + __temp1Lo; 750eae32dcSDimitry Andric const uint64_t __temp2Hi = __b01Hi + (__temp2Lo < __b01Lo); 760eae32dcSDimitry Andric return __b11Lo + __temp1Hi + __temp2Hi; 770eae32dcSDimitry Andric } 780eae32dcSDimitry Andric 790eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __uint128_mod1e9(const uint64_t __vHi, const uint64_t __vLo) { 800eae32dcSDimitry Andric // After multiplying, we're going to shift right by 29, then truncate to uint32_t. 810eae32dcSDimitry Andric // This means that we need only 29 + 32 = 61 bits, so we can truncate to uint64_t before shifting. 820eae32dcSDimitry Andric const uint64_t __multiplied = __umul256_hi128_lo64(__vHi, __vLo, 0x89705F4136B4A597u, 0x31680A88F8953031u); 830eae32dcSDimitry Andric 840eae32dcSDimitry Andric // For uint32_t truncation, see the __mod1e9() comment in d2s_intrinsics.h. 850eae32dcSDimitry Andric const uint32_t __shifted = static_cast<uint32_t>(__multiplied >> 29); 860eae32dcSDimitry Andric 870eae32dcSDimitry Andric return static_cast<uint32_t>(__vLo) - 1000000000 * __shifted; 880eae32dcSDimitry Andric } 890eae32dcSDimitry Andric #endif // ^^^ intrinsics available ^^^ 900eae32dcSDimitry Andric 910eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mulShift_mod1e9(const uint64_t __m, const uint64_t* const __mul, const int32_t __j) { 920eae32dcSDimitry Andric uint64_t __high0; // 64 930eae32dcSDimitry Andric const uint64_t __low0 = __ryu_umul128(__m, __mul[0], &__high0); // 0 940eae32dcSDimitry Andric uint64_t __high1; // 128 950eae32dcSDimitry Andric const uint64_t __low1 = __ryu_umul128(__m, __mul[1], &__high1); // 64 960eae32dcSDimitry Andric uint64_t __high2; // 192 970eae32dcSDimitry Andric const uint64_t __low2 = __ryu_umul128(__m, __mul[2], &__high2); // 128 980eae32dcSDimitry Andric const uint64_t __s0low = __low0; // 0 990eae32dcSDimitry Andric (void) __s0low; // unused 1000eae32dcSDimitry Andric const uint64_t __s0high = __low1 + __high0; // 64 1010eae32dcSDimitry Andric const uint32_t __c1 = __s0high < __low1; 1020eae32dcSDimitry Andric const uint64_t __s1low = __low2 + __high1 + __c1; // 128 1030eae32dcSDimitry Andric const uint32_t __c2 = __s1low < __low2; // __high1 + __c1 can't overflow, so compare against __low2 1040eae32dcSDimitry Andric const uint64_t __s1high = __high2 + __c2; // 192 105*5f757f3fSDimitry Andric _LIBCPP_ASSERT_INTERNAL(__j >= 128, ""); 106*5f757f3fSDimitry Andric _LIBCPP_ASSERT_INTERNAL(__j <= 180, ""); 1070eae32dcSDimitry Andric #ifdef _LIBCPP_INTRINSIC128 1080eae32dcSDimitry Andric const uint32_t __dist = static_cast<uint32_t>(__j - 128); // __dist: [0, 52] 1090eae32dcSDimitry Andric const uint64_t __shiftedhigh = __s1high >> __dist; 1100eae32dcSDimitry Andric const uint64_t __shiftedlow = __ryu_shiftright128(__s1low, __s1high, __dist); 1110eae32dcSDimitry Andric return __uint128_mod1e9(__shiftedhigh, __shiftedlow); 1120eae32dcSDimitry Andric #else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv 1130eae32dcSDimitry Andric if (__j < 160) { // __j: [128, 160) 1140eae32dcSDimitry Andric const uint64_t __r0 = __mod1e9(__s1high); 1150eae32dcSDimitry Andric const uint64_t __r1 = __mod1e9((__r0 << 32) | (__s1low >> 32)); 1160eae32dcSDimitry Andric const uint64_t __r2 = ((__r1 << 32) | (__s1low & 0xffffffff)); 1170eae32dcSDimitry Andric return __mod1e9(__r2 >> (__j - 128)); 1180eae32dcSDimitry Andric } else { // __j: [160, 192) 1190eae32dcSDimitry Andric const uint64_t __r0 = __mod1e9(__s1high); 1200eae32dcSDimitry Andric const uint64_t __r1 = ((__r0 << 32) | (__s1low >> 32)); 1210eae32dcSDimitry Andric return __mod1e9(__r1 >> (__j - 160)); 1220eae32dcSDimitry Andric } 1230eae32dcSDimitry Andric #endif // ^^^ intrinsics unavailable ^^^ 1240eae32dcSDimitry Andric } 1250eae32dcSDimitry Andric 1260eae32dcSDimitry Andric void __append_n_digits(const uint32_t __olength, uint32_t __digits, char* const __result) { 1270eae32dcSDimitry Andric uint32_t __i = 0; 1280eae32dcSDimitry Andric while (__digits >= 10000) { 1290eae32dcSDimitry Andric #ifdef __clang__ // TRANSITION, LLVM-38217 1300eae32dcSDimitry Andric const uint32_t __c = __digits - 10000 * (__digits / 10000); 1310eae32dcSDimitry Andric #else 1320eae32dcSDimitry Andric const uint32_t __c = __digits % 10000; 1330eae32dcSDimitry Andric #endif 1340eae32dcSDimitry Andric __digits /= 10000; 1350eae32dcSDimitry Andric const uint32_t __c0 = (__c % 100) << 1; 1360eae32dcSDimitry Andric const uint32_t __c1 = (__c / 100) << 1; 13706c3fb27SDimitry Andric std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c0, 2); 13806c3fb27SDimitry Andric std::memcpy(__result + __olength - __i - 4, __DIGIT_TABLE + __c1, 2); 1390eae32dcSDimitry Andric __i += 4; 1400eae32dcSDimitry Andric } 1410eae32dcSDimitry Andric if (__digits >= 100) { 1420eae32dcSDimitry Andric const uint32_t __c = (__digits % 100) << 1; 1430eae32dcSDimitry Andric __digits /= 100; 14406c3fb27SDimitry Andric std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2); 1450eae32dcSDimitry Andric __i += 2; 1460eae32dcSDimitry Andric } 1470eae32dcSDimitry Andric if (__digits >= 10) { 1480eae32dcSDimitry Andric const uint32_t __c = __digits << 1; 14906c3fb27SDimitry Andric std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2); 1500eae32dcSDimitry Andric } else { 1510eae32dcSDimitry Andric __result[0] = static_cast<char>('0' + __digits); 1520eae32dcSDimitry Andric } 1530eae32dcSDimitry Andric } 1540eae32dcSDimitry Andric 1550eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __append_d_digits(const uint32_t __olength, uint32_t __digits, char* const __result) { 1560eae32dcSDimitry Andric uint32_t __i = 0; 1570eae32dcSDimitry Andric while (__digits >= 10000) { 1580eae32dcSDimitry Andric #ifdef __clang__ // TRANSITION, LLVM-38217 1590eae32dcSDimitry Andric const uint32_t __c = __digits - 10000 * (__digits / 10000); 1600eae32dcSDimitry Andric #else 1610eae32dcSDimitry Andric const uint32_t __c = __digits % 10000; 1620eae32dcSDimitry Andric #endif 1630eae32dcSDimitry Andric __digits /= 10000; 1640eae32dcSDimitry Andric const uint32_t __c0 = (__c % 100) << 1; 1650eae32dcSDimitry Andric const uint32_t __c1 = (__c / 100) << 1; 16606c3fb27SDimitry Andric std::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c0, 2); 16706c3fb27SDimitry Andric std::memcpy(__result + __olength + 1 - __i - 4, __DIGIT_TABLE + __c1, 2); 1680eae32dcSDimitry Andric __i += 4; 1690eae32dcSDimitry Andric } 1700eae32dcSDimitry Andric if (__digits >= 100) { 1710eae32dcSDimitry Andric const uint32_t __c = (__digits % 100) << 1; 1720eae32dcSDimitry Andric __digits /= 100; 17306c3fb27SDimitry Andric std::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c, 2); 1740eae32dcSDimitry Andric __i += 2; 1750eae32dcSDimitry Andric } 1760eae32dcSDimitry Andric if (__digits >= 10) { 1770eae32dcSDimitry Andric const uint32_t __c = __digits << 1; 1780eae32dcSDimitry Andric __result[2] = __DIGIT_TABLE[__c + 1]; 1790eae32dcSDimitry Andric __result[1] = '.'; 1800eae32dcSDimitry Andric __result[0] = __DIGIT_TABLE[__c]; 1810eae32dcSDimitry Andric } else { 1820eae32dcSDimitry Andric __result[1] = '.'; 1830eae32dcSDimitry Andric __result[0] = static_cast<char>('0' + __digits); 1840eae32dcSDimitry Andric } 1850eae32dcSDimitry Andric } 1860eae32dcSDimitry Andric 1870eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __append_c_digits(const uint32_t __count, uint32_t __digits, char* const __result) { 1880eae32dcSDimitry Andric uint32_t __i = 0; 1890eae32dcSDimitry Andric for (; __i < __count - 1; __i += 2) { 1900eae32dcSDimitry Andric const uint32_t __c = (__digits % 100) << 1; 1910eae32dcSDimitry Andric __digits /= 100; 19206c3fb27SDimitry Andric std::memcpy(__result + __count - __i - 2, __DIGIT_TABLE + __c, 2); 1930eae32dcSDimitry Andric } 1940eae32dcSDimitry Andric if (__i < __count) { 1950eae32dcSDimitry Andric const char __c = static_cast<char>('0' + (__digits % 10)); 1960eae32dcSDimitry Andric __result[__count - __i - 1] = __c; 1970eae32dcSDimitry Andric } 1980eae32dcSDimitry Andric } 1990eae32dcSDimitry Andric 2000eae32dcSDimitry Andric void __append_nine_digits(uint32_t __digits, char* const __result) { 2010eae32dcSDimitry Andric if (__digits == 0) { 20206c3fb27SDimitry Andric std::memset(__result, '0', 9); 2030eae32dcSDimitry Andric return; 2040eae32dcSDimitry Andric } 2050eae32dcSDimitry Andric 2060eae32dcSDimitry Andric for (uint32_t __i = 0; __i < 5; __i += 4) { 2070eae32dcSDimitry Andric #ifdef __clang__ // TRANSITION, LLVM-38217 2080eae32dcSDimitry Andric const uint32_t __c = __digits - 10000 * (__digits / 10000); 2090eae32dcSDimitry Andric #else 2100eae32dcSDimitry Andric const uint32_t __c = __digits % 10000; 2110eae32dcSDimitry Andric #endif 2120eae32dcSDimitry Andric __digits /= 10000; 2130eae32dcSDimitry Andric const uint32_t __c0 = (__c % 100) << 1; 2140eae32dcSDimitry Andric const uint32_t __c1 = (__c / 100) << 1; 21506c3fb27SDimitry Andric std::memcpy(__result + 7 - __i, __DIGIT_TABLE + __c0, 2); 21606c3fb27SDimitry Andric std::memcpy(__result + 5 - __i, __DIGIT_TABLE + __c1, 2); 2170eae32dcSDimitry Andric } 2180eae32dcSDimitry Andric __result[0] = static_cast<char>('0' + __digits); 2190eae32dcSDimitry Andric } 2200eae32dcSDimitry Andric 2210eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __indexForExponent(const uint32_t __e) { 2220eae32dcSDimitry Andric return (__e + 15) / 16; 2230eae32dcSDimitry Andric } 2240eae32dcSDimitry Andric 2250eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __pow10BitsForIndex(const uint32_t __idx) { 2260eae32dcSDimitry Andric return 16 * __idx + __POW10_ADDITIONAL_BITS; 2270eae32dcSDimitry Andric } 2280eae32dcSDimitry Andric 2290eae32dcSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __lengthForIndex(const uint32_t __idx) { 2300eae32dcSDimitry Andric // +1 for ceil, +16 for mantissa, +8 to round up when dividing by 9 2310eae32dcSDimitry Andric return (__log10Pow2(16 * static_cast<int32_t>(__idx)) + 1 + 16 + 8) / 9; 2320eae32dcSDimitry Andric } 2330eae32dcSDimitry Andric 2340eae32dcSDimitry Andric [[nodiscard]] to_chars_result __d2fixed_buffered_n(char* _First, char* const _Last, const double __d, 2350eae32dcSDimitry Andric const uint32_t __precision) { 2360eae32dcSDimitry Andric char* const _Original_first = _First; 2370eae32dcSDimitry Andric 2380eae32dcSDimitry Andric const uint64_t __bits = __double_to_bits(__d); 2390eae32dcSDimitry Andric 2400eae32dcSDimitry Andric // Case distinction; exit early for the easy cases. 2410eae32dcSDimitry Andric if (__bits == 0) { 2420eae32dcSDimitry Andric const int32_t _Total_zero_length = 1 // leading zero 2430eae32dcSDimitry Andric + static_cast<int32_t>(__precision != 0) // possible decimal point 2440eae32dcSDimitry Andric + static_cast<int32_t>(__precision); // zeroes after decimal point 2450eae32dcSDimitry Andric 2460eae32dcSDimitry Andric if (_Last - _First < _Total_zero_length) { 2470eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 2480eae32dcSDimitry Andric } 2490eae32dcSDimitry Andric 2500eae32dcSDimitry Andric *_First++ = '0'; 2510eae32dcSDimitry Andric if (__precision > 0) { 2520eae32dcSDimitry Andric *_First++ = '.'; 25306c3fb27SDimitry Andric std::memset(_First, '0', __precision); 2540eae32dcSDimitry Andric _First += __precision; 2550eae32dcSDimitry Andric } 2560eae32dcSDimitry Andric return { _First, errc{} }; 2570eae32dcSDimitry Andric } 2580eae32dcSDimitry Andric 2590eae32dcSDimitry Andric // Decode __bits into mantissa and exponent. 2600eae32dcSDimitry Andric const uint64_t __ieeeMantissa = __bits & ((1ull << __DOUBLE_MANTISSA_BITS) - 1); 2610eae32dcSDimitry Andric const uint32_t __ieeeExponent = static_cast<uint32_t>(__bits >> __DOUBLE_MANTISSA_BITS); 2620eae32dcSDimitry Andric 2630eae32dcSDimitry Andric int32_t __e2; 2640eae32dcSDimitry Andric uint64_t __m2; 2650eae32dcSDimitry Andric if (__ieeeExponent == 0) { 2660eae32dcSDimitry Andric __e2 = 1 - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS; 2670eae32dcSDimitry Andric __m2 = __ieeeMantissa; 2680eae32dcSDimitry Andric } else { 2690eae32dcSDimitry Andric __e2 = static_cast<int32_t>(__ieeeExponent) - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS; 2700eae32dcSDimitry Andric __m2 = (1ull << __DOUBLE_MANTISSA_BITS) | __ieeeMantissa; 2710eae32dcSDimitry Andric } 2720eae32dcSDimitry Andric 2730eae32dcSDimitry Andric bool __nonzero = false; 2740eae32dcSDimitry Andric if (__e2 >= -52) { 2750eae32dcSDimitry Andric const uint32_t __idx = __e2 < 0 ? 0 : __indexForExponent(static_cast<uint32_t>(__e2)); 2760eae32dcSDimitry Andric const uint32_t __p10bits = __pow10BitsForIndex(__idx); 2770eae32dcSDimitry Andric const int32_t __len = static_cast<int32_t>(__lengthForIndex(__idx)); 2780eae32dcSDimitry Andric for (int32_t __i = __len - 1; __i >= 0; --__i) { 2790eae32dcSDimitry Andric const uint32_t __j = __p10bits - __e2; 2800eae32dcSDimitry Andric // Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is 2810eae32dcSDimitry Andric // a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers. 2820eae32dcSDimitry Andric const uint32_t __digits = __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT[__POW10_OFFSET[__idx] + __i], 2830eae32dcSDimitry Andric static_cast<int32_t>(__j + 8)); 2840eae32dcSDimitry Andric if (__nonzero) { 2850eae32dcSDimitry Andric if (_Last - _First < 9) { 2860eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 2870eae32dcSDimitry Andric } 2880eae32dcSDimitry Andric __append_nine_digits(__digits, _First); 2890eae32dcSDimitry Andric _First += 9; 2900eae32dcSDimitry Andric } else if (__digits != 0) { 2910eae32dcSDimitry Andric const uint32_t __olength = __decimalLength9(__digits); 2920eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__olength)) { 2930eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 2940eae32dcSDimitry Andric } 2950eae32dcSDimitry Andric __append_n_digits(__olength, __digits, _First); 2960eae32dcSDimitry Andric _First += __olength; 2970eae32dcSDimitry Andric __nonzero = true; 2980eae32dcSDimitry Andric } 2990eae32dcSDimitry Andric } 3000eae32dcSDimitry Andric } 3010eae32dcSDimitry Andric if (!__nonzero) { 3020eae32dcSDimitry Andric if (_First == _Last) { 3030eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3040eae32dcSDimitry Andric } 3050eae32dcSDimitry Andric *_First++ = '0'; 3060eae32dcSDimitry Andric } 3070eae32dcSDimitry Andric if (__precision > 0) { 3080eae32dcSDimitry Andric if (_First == _Last) { 3090eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3100eae32dcSDimitry Andric } 3110eae32dcSDimitry Andric *_First++ = '.'; 3120eae32dcSDimitry Andric } 3130eae32dcSDimitry Andric if (__e2 < 0) { 3140eae32dcSDimitry Andric const int32_t __idx = -__e2 / 16; 3150eae32dcSDimitry Andric const uint32_t __blocks = __precision / 9 + 1; 3160eae32dcSDimitry Andric // 0 = don't round up; 1 = round up unconditionally; 2 = round up if odd. 3170eae32dcSDimitry Andric int __roundUp = 0; 3180eae32dcSDimitry Andric uint32_t __i = 0; 3190eae32dcSDimitry Andric if (__blocks <= __MIN_BLOCK_2[__idx]) { 3200eae32dcSDimitry Andric __i = __blocks; 3210eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__precision)) { 3220eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3230eae32dcSDimitry Andric } 32406c3fb27SDimitry Andric std::memset(_First, '0', __precision); 3250eae32dcSDimitry Andric _First += __precision; 3260eae32dcSDimitry Andric } else if (__i < __MIN_BLOCK_2[__idx]) { 3270eae32dcSDimitry Andric __i = __MIN_BLOCK_2[__idx]; 3280eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(9 * __i)) { 3290eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3300eae32dcSDimitry Andric } 33106c3fb27SDimitry Andric std::memset(_First, '0', 9 * __i); 3320eae32dcSDimitry Andric _First += 9 * __i; 3330eae32dcSDimitry Andric } 3340eae32dcSDimitry Andric for (; __i < __blocks; ++__i) { 3350eae32dcSDimitry Andric const int32_t __j = __ADDITIONAL_BITS_2 + (-__e2 - 16 * __idx); 3360eae32dcSDimitry Andric const uint32_t __p = __POW10_OFFSET_2[__idx] + __i - __MIN_BLOCK_2[__idx]; 3370eae32dcSDimitry Andric if (__p >= __POW10_OFFSET_2[__idx + 1]) { 3380eae32dcSDimitry Andric // If the remaining digits are all 0, then we might as well use memset. 3390eae32dcSDimitry Andric // No rounding required in this case. 3400eae32dcSDimitry Andric const uint32_t __fill = __precision - 9 * __i; 3410eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__fill)) { 3420eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3430eae32dcSDimitry Andric } 34406c3fb27SDimitry Andric std::memset(_First, '0', __fill); 3450eae32dcSDimitry Andric _First += __fill; 3460eae32dcSDimitry Andric break; 3470eae32dcSDimitry Andric } 3480eae32dcSDimitry Andric // Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is 3490eae32dcSDimitry Andric // a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers. 3500eae32dcSDimitry Andric uint32_t __digits = __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT_2[__p], __j + 8); 3510eae32dcSDimitry Andric if (__i < __blocks - 1) { 3520eae32dcSDimitry Andric if (_Last - _First < 9) { 3530eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3540eae32dcSDimitry Andric } 3550eae32dcSDimitry Andric __append_nine_digits(__digits, _First); 3560eae32dcSDimitry Andric _First += 9; 3570eae32dcSDimitry Andric } else { 3580eae32dcSDimitry Andric const uint32_t __maximum = __precision - 9 * __i; 3590eae32dcSDimitry Andric uint32_t __lastDigit = 0; 3600eae32dcSDimitry Andric for (uint32_t __k = 0; __k < 9 - __maximum; ++__k) { 3610eae32dcSDimitry Andric __lastDigit = __digits % 10; 3620eae32dcSDimitry Andric __digits /= 10; 3630eae32dcSDimitry Andric } 3640eae32dcSDimitry Andric if (__lastDigit != 5) { 3650eae32dcSDimitry Andric __roundUp = __lastDigit > 5; 3660eae32dcSDimitry Andric } else { 3670eae32dcSDimitry Andric // Is m * 10^(additionalDigits + 1) / 2^(-__e2) integer? 3680eae32dcSDimitry Andric const int32_t __requiredTwos = -__e2 - static_cast<int32_t>(__precision) - 1; 3690eae32dcSDimitry Andric const bool __trailingZeros = __requiredTwos <= 0 3700eae32dcSDimitry Andric || (__requiredTwos < 60 && __multipleOfPowerOf2(__m2, static_cast<uint32_t>(__requiredTwos))); 3710eae32dcSDimitry Andric __roundUp = __trailingZeros ? 2 : 1; 3720eae32dcSDimitry Andric } 3730eae32dcSDimitry Andric if (__maximum > 0) { 3740eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__maximum)) { 3750eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3760eae32dcSDimitry Andric } 3770eae32dcSDimitry Andric __append_c_digits(__maximum, __digits, _First); 3780eae32dcSDimitry Andric _First += __maximum; 3790eae32dcSDimitry Andric } 3800eae32dcSDimitry Andric break; 3810eae32dcSDimitry Andric } 3820eae32dcSDimitry Andric } 3830eae32dcSDimitry Andric if (__roundUp != 0) { 3840eae32dcSDimitry Andric char* _Round = _First; 3850eae32dcSDimitry Andric char* _Dot = _Last; 3860eae32dcSDimitry Andric while (true) { 3870eae32dcSDimitry Andric if (_Round == _Original_first) { 3880eae32dcSDimitry Andric _Round[0] = '1'; 3890eae32dcSDimitry Andric if (_Dot != _Last) { 3900eae32dcSDimitry Andric _Dot[0] = '0'; 3910eae32dcSDimitry Andric _Dot[1] = '.'; 3920eae32dcSDimitry Andric } 3930eae32dcSDimitry Andric if (_First == _Last) { 3940eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 3950eae32dcSDimitry Andric } 3960eae32dcSDimitry Andric *_First++ = '0'; 3970eae32dcSDimitry Andric break; 3980eae32dcSDimitry Andric } 3990eae32dcSDimitry Andric --_Round; 4000eae32dcSDimitry Andric const char __c = _Round[0]; 4010eae32dcSDimitry Andric if (__c == '.') { 4020eae32dcSDimitry Andric _Dot = _Round; 4030eae32dcSDimitry Andric } else if (__c == '9') { 4040eae32dcSDimitry Andric _Round[0] = '0'; 4050eae32dcSDimitry Andric __roundUp = 1; 4060eae32dcSDimitry Andric } else { 4070eae32dcSDimitry Andric if (__roundUp == 1 || __c % 2 != 0) { 4080eae32dcSDimitry Andric _Round[0] = __c + 1; 4090eae32dcSDimitry Andric } 4100eae32dcSDimitry Andric break; 4110eae32dcSDimitry Andric } 4120eae32dcSDimitry Andric } 4130eae32dcSDimitry Andric } 4140eae32dcSDimitry Andric } else { 4150eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__precision)) { 4160eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 4170eae32dcSDimitry Andric } 41806c3fb27SDimitry Andric std::memset(_First, '0', __precision); 4190eae32dcSDimitry Andric _First += __precision; 4200eae32dcSDimitry Andric } 4210eae32dcSDimitry Andric return { _First, errc{} }; 4220eae32dcSDimitry Andric } 4230eae32dcSDimitry Andric 4240eae32dcSDimitry Andric [[nodiscard]] to_chars_result __d2exp_buffered_n(char* _First, char* const _Last, const double __d, 4250eae32dcSDimitry Andric uint32_t __precision) { 4260eae32dcSDimitry Andric char* const _Original_first = _First; 4270eae32dcSDimitry Andric 4280eae32dcSDimitry Andric const uint64_t __bits = __double_to_bits(__d); 4290eae32dcSDimitry Andric 4300eae32dcSDimitry Andric // Case distinction; exit early for the easy cases. 4310eae32dcSDimitry Andric if (__bits == 0) { 4320eae32dcSDimitry Andric const int32_t _Total_zero_length = 1 // leading zero 4330eae32dcSDimitry Andric + static_cast<int32_t>(__precision != 0) // possible decimal point 4340eae32dcSDimitry Andric + static_cast<int32_t>(__precision) // zeroes after decimal point 4350eae32dcSDimitry Andric + 4; // "e+00" 4360eae32dcSDimitry Andric if (_Last - _First < _Total_zero_length) { 4370eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 4380eae32dcSDimitry Andric } 4390eae32dcSDimitry Andric *_First++ = '0'; 4400eae32dcSDimitry Andric if (__precision > 0) { 4410eae32dcSDimitry Andric *_First++ = '.'; 44206c3fb27SDimitry Andric std::memset(_First, '0', __precision); 4430eae32dcSDimitry Andric _First += __precision; 4440eae32dcSDimitry Andric } 44506c3fb27SDimitry Andric std::memcpy(_First, "e+00", 4); 4460eae32dcSDimitry Andric _First += 4; 4470eae32dcSDimitry Andric return { _First, errc{} }; 4480eae32dcSDimitry Andric } 4490eae32dcSDimitry Andric 4500eae32dcSDimitry Andric // Decode __bits into mantissa and exponent. 4510eae32dcSDimitry Andric const uint64_t __ieeeMantissa = __bits & ((1ull << __DOUBLE_MANTISSA_BITS) - 1); 4520eae32dcSDimitry Andric const uint32_t __ieeeExponent = static_cast<uint32_t>(__bits >> __DOUBLE_MANTISSA_BITS); 4530eae32dcSDimitry Andric 4540eae32dcSDimitry Andric int32_t __e2; 4550eae32dcSDimitry Andric uint64_t __m2; 4560eae32dcSDimitry Andric if (__ieeeExponent == 0) { 4570eae32dcSDimitry Andric __e2 = 1 - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS; 4580eae32dcSDimitry Andric __m2 = __ieeeMantissa; 4590eae32dcSDimitry Andric } else { 4600eae32dcSDimitry Andric __e2 = static_cast<int32_t>(__ieeeExponent) - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS; 4610eae32dcSDimitry Andric __m2 = (1ull << __DOUBLE_MANTISSA_BITS) | __ieeeMantissa; 4620eae32dcSDimitry Andric } 4630eae32dcSDimitry Andric 4640eae32dcSDimitry Andric const bool __printDecimalPoint = __precision > 0; 4650eae32dcSDimitry Andric ++__precision; 4660eae32dcSDimitry Andric uint32_t __digits = 0; 4670eae32dcSDimitry Andric uint32_t __printedDigits = 0; 4680eae32dcSDimitry Andric uint32_t __availableDigits = 0; 4690eae32dcSDimitry Andric int32_t __exp = 0; 4700eae32dcSDimitry Andric if (__e2 >= -52) { 4710eae32dcSDimitry Andric const uint32_t __idx = __e2 < 0 ? 0 : __indexForExponent(static_cast<uint32_t>(__e2)); 4720eae32dcSDimitry Andric const uint32_t __p10bits = __pow10BitsForIndex(__idx); 4730eae32dcSDimitry Andric const int32_t __len = static_cast<int32_t>(__lengthForIndex(__idx)); 4740eae32dcSDimitry Andric for (int32_t __i = __len - 1; __i >= 0; --__i) { 4750eae32dcSDimitry Andric const uint32_t __j = __p10bits - __e2; 4760eae32dcSDimitry Andric // Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is 4770eae32dcSDimitry Andric // a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers. 4780eae32dcSDimitry Andric __digits = __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT[__POW10_OFFSET[__idx] + __i], 4790eae32dcSDimitry Andric static_cast<int32_t>(__j + 8)); 4800eae32dcSDimitry Andric if (__printedDigits != 0) { 4810eae32dcSDimitry Andric if (__printedDigits + 9 > __precision) { 4820eae32dcSDimitry Andric __availableDigits = 9; 4830eae32dcSDimitry Andric break; 4840eae32dcSDimitry Andric } 4850eae32dcSDimitry Andric if (_Last - _First < 9) { 4860eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 4870eae32dcSDimitry Andric } 4880eae32dcSDimitry Andric __append_nine_digits(__digits, _First); 4890eae32dcSDimitry Andric _First += 9; 4900eae32dcSDimitry Andric __printedDigits += 9; 4910eae32dcSDimitry Andric } else if (__digits != 0) { 4920eae32dcSDimitry Andric __availableDigits = __decimalLength9(__digits); 4930eae32dcSDimitry Andric __exp = __i * 9 + static_cast<int32_t>(__availableDigits) - 1; 4940eae32dcSDimitry Andric if (__availableDigits > __precision) { 4950eae32dcSDimitry Andric break; 4960eae32dcSDimitry Andric } 4970eae32dcSDimitry Andric if (__printDecimalPoint) { 4980eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__availableDigits + 1)) { 4990eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 5000eae32dcSDimitry Andric } 5010eae32dcSDimitry Andric __append_d_digits(__availableDigits, __digits, _First); 5020eae32dcSDimitry Andric _First += __availableDigits + 1; // +1 for decimal point 5030eae32dcSDimitry Andric } else { 5040eae32dcSDimitry Andric if (_First == _Last) { 5050eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 5060eae32dcSDimitry Andric } 5070eae32dcSDimitry Andric *_First++ = static_cast<char>('0' + __digits); 5080eae32dcSDimitry Andric } 5090eae32dcSDimitry Andric __printedDigits = __availableDigits; 5100eae32dcSDimitry Andric __availableDigits = 0; 5110eae32dcSDimitry Andric } 5120eae32dcSDimitry Andric } 5130eae32dcSDimitry Andric } 5140eae32dcSDimitry Andric 5150eae32dcSDimitry Andric if (__e2 < 0 && __availableDigits == 0) { 5160eae32dcSDimitry Andric const int32_t __idx = -__e2 / 16; 5170eae32dcSDimitry Andric for (int32_t __i = __MIN_BLOCK_2[__idx]; __i < 200; ++__i) { 5180eae32dcSDimitry Andric const int32_t __j = __ADDITIONAL_BITS_2 + (-__e2 - 16 * __idx); 5190eae32dcSDimitry Andric const uint32_t __p = __POW10_OFFSET_2[__idx] + static_cast<uint32_t>(__i) - __MIN_BLOCK_2[__idx]; 5200eae32dcSDimitry Andric // Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is 5210eae32dcSDimitry Andric // a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers. 5220eae32dcSDimitry Andric __digits = (__p >= __POW10_OFFSET_2[__idx + 1]) ? 0 : __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT_2[__p], __j + 8); 5230eae32dcSDimitry Andric if (__printedDigits != 0) { 5240eae32dcSDimitry Andric if (__printedDigits + 9 > __precision) { 5250eae32dcSDimitry Andric __availableDigits = 9; 5260eae32dcSDimitry Andric break; 5270eae32dcSDimitry Andric } 5280eae32dcSDimitry Andric if (_Last - _First < 9) { 5290eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 5300eae32dcSDimitry Andric } 5310eae32dcSDimitry Andric __append_nine_digits(__digits, _First); 5320eae32dcSDimitry Andric _First += 9; 5330eae32dcSDimitry Andric __printedDigits += 9; 5340eae32dcSDimitry Andric } else if (__digits != 0) { 5350eae32dcSDimitry Andric __availableDigits = __decimalLength9(__digits); 5360eae32dcSDimitry Andric __exp = -(__i + 1) * 9 + static_cast<int32_t>(__availableDigits) - 1; 5370eae32dcSDimitry Andric if (__availableDigits > __precision) { 5380eae32dcSDimitry Andric break; 5390eae32dcSDimitry Andric } 5400eae32dcSDimitry Andric if (__printDecimalPoint) { 5410eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__availableDigits + 1)) { 5420eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 5430eae32dcSDimitry Andric } 5440eae32dcSDimitry Andric __append_d_digits(__availableDigits, __digits, _First); 5450eae32dcSDimitry Andric _First += __availableDigits + 1; // +1 for decimal point 5460eae32dcSDimitry Andric } else { 5470eae32dcSDimitry Andric if (_First == _Last) { 5480eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 5490eae32dcSDimitry Andric } 5500eae32dcSDimitry Andric *_First++ = static_cast<char>('0' + __digits); 5510eae32dcSDimitry Andric } 5520eae32dcSDimitry Andric __printedDigits = __availableDigits; 5530eae32dcSDimitry Andric __availableDigits = 0; 5540eae32dcSDimitry Andric } 5550eae32dcSDimitry Andric } 5560eae32dcSDimitry Andric } 5570eae32dcSDimitry Andric 5580eae32dcSDimitry Andric const uint32_t __maximum = __precision - __printedDigits; 5590eae32dcSDimitry Andric if (__availableDigits == 0) { 5600eae32dcSDimitry Andric __digits = 0; 5610eae32dcSDimitry Andric } 5620eae32dcSDimitry Andric uint32_t __lastDigit = 0; 5630eae32dcSDimitry Andric if (__availableDigits > __maximum) { 5640eae32dcSDimitry Andric for (uint32_t __k = 0; __k < __availableDigits - __maximum; ++__k) { 5650eae32dcSDimitry Andric __lastDigit = __digits % 10; 5660eae32dcSDimitry Andric __digits /= 10; 5670eae32dcSDimitry Andric } 5680eae32dcSDimitry Andric } 5690eae32dcSDimitry Andric // 0 = don't round up; 1 = round up unconditionally; 2 = round up if odd. 5700eae32dcSDimitry Andric int __roundUp = 0; 5710eae32dcSDimitry Andric if (__lastDigit != 5) { 5720eae32dcSDimitry Andric __roundUp = __lastDigit > 5; 5730eae32dcSDimitry Andric } else { 5740eae32dcSDimitry Andric // Is m * 2^__e2 * 10^(__precision + 1 - __exp) integer? 5750eae32dcSDimitry Andric // __precision was already increased by 1, so we don't need to write + 1 here. 5760eae32dcSDimitry Andric const int32_t __rexp = static_cast<int32_t>(__precision) - __exp; 5770eae32dcSDimitry Andric const int32_t __requiredTwos = -__e2 - __rexp; 5780eae32dcSDimitry Andric bool __trailingZeros = __requiredTwos <= 0 5790eae32dcSDimitry Andric || (__requiredTwos < 60 && __multipleOfPowerOf2(__m2, static_cast<uint32_t>(__requiredTwos))); 5800eae32dcSDimitry Andric if (__rexp < 0) { 5810eae32dcSDimitry Andric const int32_t __requiredFives = -__rexp; 5820eae32dcSDimitry Andric __trailingZeros = __trailingZeros && __multipleOfPowerOf5(__m2, static_cast<uint32_t>(__requiredFives)); 5830eae32dcSDimitry Andric } 5840eae32dcSDimitry Andric __roundUp = __trailingZeros ? 2 : 1; 5850eae32dcSDimitry Andric } 5860eae32dcSDimitry Andric if (__printedDigits != 0) { 5870eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__maximum)) { 5880eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 5890eae32dcSDimitry Andric } 5900eae32dcSDimitry Andric if (__digits == 0) { 59106c3fb27SDimitry Andric std::memset(_First, '0', __maximum); 5920eae32dcSDimitry Andric } else { 5930eae32dcSDimitry Andric __append_c_digits(__maximum, __digits, _First); 5940eae32dcSDimitry Andric } 5950eae32dcSDimitry Andric _First += __maximum; 5960eae32dcSDimitry Andric } else { 5970eae32dcSDimitry Andric if (__printDecimalPoint) { 5980eae32dcSDimitry Andric if (_Last - _First < static_cast<ptrdiff_t>(__maximum + 1)) { 5990eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 6000eae32dcSDimitry Andric } 6010eae32dcSDimitry Andric __append_d_digits(__maximum, __digits, _First); 6020eae32dcSDimitry Andric _First += __maximum + 1; // +1 for decimal point 6030eae32dcSDimitry Andric } else { 6040eae32dcSDimitry Andric if (_First == _Last) { 6050eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 6060eae32dcSDimitry Andric } 6070eae32dcSDimitry Andric *_First++ = static_cast<char>('0' + __digits); 6080eae32dcSDimitry Andric } 6090eae32dcSDimitry Andric } 6100eae32dcSDimitry Andric if (__roundUp != 0) { 6110eae32dcSDimitry Andric char* _Round = _First; 6120eae32dcSDimitry Andric while (true) { 6130eae32dcSDimitry Andric if (_Round == _Original_first) { 6140eae32dcSDimitry Andric _Round[0] = '1'; 6150eae32dcSDimitry Andric ++__exp; 6160eae32dcSDimitry Andric break; 6170eae32dcSDimitry Andric } 6180eae32dcSDimitry Andric --_Round; 6190eae32dcSDimitry Andric const char __c = _Round[0]; 6200eae32dcSDimitry Andric if (__c == '.') { 6210eae32dcSDimitry Andric // Keep going. 6220eae32dcSDimitry Andric } else if (__c == '9') { 6230eae32dcSDimitry Andric _Round[0] = '0'; 6240eae32dcSDimitry Andric __roundUp = 1; 6250eae32dcSDimitry Andric } else { 6260eae32dcSDimitry Andric if (__roundUp == 1 || __c % 2 != 0) { 6270eae32dcSDimitry Andric _Round[0] = __c + 1; 6280eae32dcSDimitry Andric } 6290eae32dcSDimitry Andric break; 6300eae32dcSDimitry Andric } 6310eae32dcSDimitry Andric } 6320eae32dcSDimitry Andric } 6330eae32dcSDimitry Andric 6340eae32dcSDimitry Andric char _Sign_character; 6350eae32dcSDimitry Andric 6360eae32dcSDimitry Andric if (__exp < 0) { 6370eae32dcSDimitry Andric _Sign_character = '-'; 6380eae32dcSDimitry Andric __exp = -__exp; 6390eae32dcSDimitry Andric } else { 6400eae32dcSDimitry Andric _Sign_character = '+'; 6410eae32dcSDimitry Andric } 6420eae32dcSDimitry Andric 6430eae32dcSDimitry Andric const int _Exponent_part_length = __exp >= 100 6440eae32dcSDimitry Andric ? 5 // "e+NNN" 6450eae32dcSDimitry Andric : 4; // "e+NN" 6460eae32dcSDimitry Andric 6470eae32dcSDimitry Andric if (_Last - _First < _Exponent_part_length) { 6480eae32dcSDimitry Andric return { _Last, errc::value_too_large }; 6490eae32dcSDimitry Andric } 6500eae32dcSDimitry Andric 6510eae32dcSDimitry Andric *_First++ = 'e'; 6520eae32dcSDimitry Andric *_First++ = _Sign_character; 6530eae32dcSDimitry Andric 6540eae32dcSDimitry Andric if (__exp >= 100) { 6550eae32dcSDimitry Andric const int32_t __c = __exp % 10; 65606c3fb27SDimitry Andric std::memcpy(_First, __DIGIT_TABLE + 2 * (__exp / 10), 2); 6570eae32dcSDimitry Andric _First[2] = static_cast<char>('0' + __c); 6580eae32dcSDimitry Andric _First += 3; 6590eae32dcSDimitry Andric } else { 66006c3fb27SDimitry Andric std::memcpy(_First, __DIGIT_TABLE + 2 * __exp, 2); 6610eae32dcSDimitry Andric _First += 2; 6620eae32dcSDimitry Andric } 6630eae32dcSDimitry Andric 6640eae32dcSDimitry Andric return { _First, errc{} }; 6650eae32dcSDimitry Andric } 6660eae32dcSDimitry Andric 6670eae32dcSDimitry Andric _LIBCPP_END_NAMESPACE_STD 6680eae32dcSDimitry Andric 6690eae32dcSDimitry Andric // clang-format on 670