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