LCOV - code coverage report
Current view: top level - json/detail/dragonbox/impl - to_chars.ipp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 58.5 % 188 110
Test Date: 2026-02-03 18:58:32 Functions: 100.0 % 3 3

            Line data    Source code
       1              : // Copyright 2020-2023 Junekey Jeon
       2              : // Copyright 2022 Peter Dimov
       3              : // Copyright 2023 Matt Borland
       4              : // Distributed under the Boost Software License, Version 1.0.
       5              : // https://www.boost.org/LICENSE_1_0.txt
       6              : 
       7              : #include <boost/json/detail/format.hpp>
       8              : #include <boost/json/detail/dragonbox/to_chars_integer_impl.hpp>
       9              : #include <limits>
      10              : #include <cstring>
      11              : #include <cstdio>
      12              : #include <cstdint>
      13              : #include <cmath>
      14              : 
      15              : namespace boost {
      16              : namespace json {
      17              : namespace detail {
      18              : namespace to_chars_detail {
      19              : 
      20              : #ifdef BOOST_MSVC
      21              : # pragma warning(push)
      22              : # pragma warning(disable: 4127) // Conditional expression is constant (e.g. BOOST_IF_CONSTEXPR statements)
      23              : #endif
      24              : 
      25              :     // These "//"'s are to prevent clang-format to ruin this nice alignment.
      26              :     // Thanks to reddit user u/mcmcc:
      27              :     // https://www.reddit.com/r/cpp/comments/so3wx9/dragonbox_110_is_released_a_fast_floattostring/hw8z26r/?context=3
      28              :     static constexpr char radix_100_head_table[] = {
      29              :         '0', '.', '1', '.', '2', '.', '3', '.', '4', '.', //
      30              :         '5', '.', '6', '.', '7', '.', '8', '.', '9', '.', //
      31              :         '1', '.', '1', '.', '1', '.', '1', '.', '1', '.', //
      32              :         '1', '.', '1', '.', '1', '.', '1', '.', '1', '.', //
      33              :         '2', '.', '2', '.', '2', '.', '2', '.', '2', '.', //
      34              :         '2', '.', '2', '.', '2', '.', '2', '.', '2', '.', //
      35              :         '3', '.', '3', '.', '3', '.', '3', '.', '3', '.', //
      36              :         '3', '.', '3', '.', '3', '.', '3', '.', '3', '.', //
      37              :         '4', '.', '4', '.', '4', '.', '4', '.', '4', '.', //
      38              :         '4', '.', '4', '.', '4', '.', '4', '.', '4', '.', //
      39              :         '5', '.', '5', '.', '5', '.', '5', '.', '5', '.', //
      40              :         '5', '.', '5', '.', '5', '.', '5', '.', '5', '.', //
      41              :         '6', '.', '6', '.', '6', '.', '6', '.', '6', '.', //
      42              :         '6', '.', '6', '.', '6', '.', '6', '.', '6', '.', //
      43              :         '7', '.', '7', '.', '7', '.', '7', '.', '7', '.', //
      44              :         '7', '.', '7', '.', '7', '.', '7', '.', '7', '.', //
      45              :         '8', '.', '8', '.', '8', '.', '8', '.', '8', '.', //
      46              :         '8', '.', '8', '.', '8', '.', '8', '.', '8', '.', //
      47              :         '9', '.', '9', '.', '9', '.', '9', '.', '9', '.', //
      48              :         '9', '.', '9', '.', '9', '.', '9', '.', '9', '.'  //
      49              :     };
      50              : 
      51           22 :     static void print_1_digit(std::uint32_t n, char* buffer) noexcept
      52              :     {
      53           22 :         *buffer = char('0' + n);
      54           22 :     }
      55              : 
      56          334 :     static void print_2_digits(std::uint32_t n, char* buffer) noexcept
      57              :     {
      58          334 :         std::memcpy(buffer, radix_table + n * 2, 2);
      59          334 :     }
      60              : 
      61              :     // These digit generation routines are inspired by James Anhalt's itoa algorithm:
      62              :     // https://github.com/jeaiii/itoa
      63              :     // The main idea is for given n, find y such that floor(10^k * y / 2^32) = n holds,
      64              :     // where k is an appropriate integer depending on the length of n.
      65              :     // For example, if n = 1234567, we set k = 6. In this case, we have
      66              :     // floor(y / 2^32) = 1,
      67              :     // floor(10^2 * ((10^0 * y) mod 2^32) / 2^32) = 23,
      68              :     // floor(10^2 * ((10^2 * y) mod 2^32) / 2^32) = 45, and
      69              :     // floor(10^2 * ((10^4 * y) mod 2^32) / 2^32) = 67.
      70              :     // See https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/ for more explanation.
      71              : 
      72              :     BOOST_FORCEINLINE static void print_9_digits(std::uint32_t s32, int& exponent,
      73              :                                                 char*& buffer) noexcept
      74              :     {
      75              :         // -- IEEE-754 binary32
      76              :         // Since we do not cut trailing zeros in advance, s32 must be of 6~9 digits
      77              :         // unless the original input was subnormal.
      78              :         // In particular, when it is of 9 digits it shouldn't have any trailing zeros.
      79              :         // -- IEEE-754 binary64
      80              :         // In this case, s32 must be of 7~9 digits unless the input is subnormal,
      81              :         // and it shouldn't have any trailing zeros if it is of 9 digits.
      82          440 :         if (s32 >= 100000000)
      83              :         {
      84              :             // 9 digits.
      85              :             // 1441151882 = ceil(2^57 / 1'0000'0000) + 1
      86            0 :             auto prod = s32 * std::uint64_t(1441151882);
      87            0 :             prod >>= 25;
      88            0 :             std::memcpy(buffer, radix_100_head_table + std::uint32_t(prod >> 32) * 2, 2);
      89              : 
      90            0 :             prod = std::uint32_t(prod) * std::uint64_t(100);
      91            0 :             print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
      92            0 :             prod = std::uint32_t(prod) * std::uint64_t(100);
      93            0 :             print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
      94            0 :             prod = std::uint32_t(prod) * std::uint64_t(100);
      95            0 :             print_2_digits(std::uint32_t(prod >> 32), buffer + 6);
      96            0 :             prod = std::uint32_t(prod) * std::uint64_t(100);
      97            0 :             print_2_digits(std::uint32_t(prod >> 32), buffer + 8);
      98              : 
      99            0 :             exponent += 8;
     100            0 :             buffer += 10;
     101              :         }
     102          440 :         else if (s32 >= 1000000)
     103              :         {
     104              :             // 7 or 8 digits.
     105              :             // 281474978 = ceil(2^48 / 100'0000) + 1
     106            0 :             auto prod = s32 * std::uint64_t(281474978);
     107            0 :             prod >>= 16;
     108            0 :             const auto head_digits = std::uint32_t(prod >> 32);
     109              :             // If s32 is of 8 digits, increase the exponent by 7.
     110              :             // Otherwise, increase it by 6.
     111            0 :             exponent += static_cast<int>(6 + unsigned(head_digits >= 10));
     112              : 
     113              :             // Write the first digit and the decimal point.
     114            0 :             std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2);
     115              :             // This third character may be overwritten later, but we don't care.
     116            0 :             buffer[2] = radix_table[head_digits * 2 + 1];
     117              : 
     118              :             // Remaining 6 digits are all zero?
     119            0 :             if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 1000000))
     120              :             {
     121              :                 // The number of characters actually need to be written is:
     122              :                 //   1, if only the first digit is nonzero, which means that either s32 is of 7
     123              :                 //   digits or it is of 8 digits but the second digit is zero, or
     124              :                 //   3, otherwise.
     125              :                 // Note that buffer[2] is never '0' if s32 is of 7 digits, because the input is
     126              :                 // never zero.
     127            0 :                 buffer += (1 + (unsigned(head_digits >= 10) & unsigned(buffer[2] > '0')) * 2);
     128              :             }
     129              :             else
     130              :             {
     131              :                 // At least one of the remaining 6 digits are nonzero.
     132              :                 // After this adjustment, now the first destination becomes buffer + 2.
     133            0 :                 buffer += unsigned(head_digits >= 10);
     134              : 
     135              :                 // Obtain the next two digits.
     136            0 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     137            0 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     138              : 
     139              :                 // Remaining 4 digits are all zero?
     140            0 :                 if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 10000))
     141              :                 {
     142            0 :                     buffer += (3 + unsigned(buffer[3] > '0'));
     143              :                 }
     144              :                 else
     145              :                 {
     146              :                     // At least one of the remaining 4 digits are nonzero.
     147              : 
     148              :                     // Obtain the next two digits.
     149            0 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     150            0 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
     151              : 
     152              :                     // Remaining 2 digits are all zero?
     153            0 :                     if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 100))
     154              :                     {
     155            0 :                         buffer += (5 + unsigned(buffer[5] > '0'));
     156              :                     }
     157              :                     else
     158              :                     {
     159              :                         // Obtain the last two digits.
     160            0 :                         prod = std::uint32_t(prod) * std::uint64_t(100);
     161            0 :                         print_2_digits(std::uint32_t(prod >> 32), buffer + 6);
     162              : 
     163            0 :                         buffer += (7 + unsigned(buffer[7] > '0'));
     164              :                     }
     165              :                 }
     166              :             }
     167              :         }
     168          440 :         else if (s32 >= 10000)
     169              :         {
     170              :             // 5 or 6 digits.
     171              :             // 429497 = ceil(2^32 / 1'0000)
     172            0 :             auto prod = s32 * std::uint64_t(429497);
     173            0 :             const auto head_digits = std::uint32_t(prod >> 32);
     174              : 
     175              :             // If s32 is of 6 digits, increase the exponent by 5.
     176              :             // Otherwise, increase it by 4.
     177            0 :             exponent += static_cast<int>(4 + unsigned(head_digits >= 10));
     178              : 
     179              :             // Write the first digit and the decimal point.
     180            0 :             std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2);
     181              :             // This third character may be overwritten later but we don't care.
     182            0 :             buffer[2] = radix_table[head_digits * 2 + 1];
     183              : 
     184              :             // Remaining 4 digits are all zero?
     185            0 :             if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 10000))
     186              :             {
     187              :                 // The number of characters actually written is 1 or 3, similarly to the case of
     188              :                 // 7 or 8 digits.
     189            0 :                 buffer += (1 + (unsigned(head_digits >= 10) & unsigned(buffer[2] > '0')) * 2);
     190              :             }
     191              :             else
     192              :             {
     193              :                 // At least one of the remaining 4 digits are nonzero.
     194              :                 // After this adjustment, now the first destination becomes buffer + 2.
     195            0 :                 buffer += unsigned(head_digits >= 10);
     196              : 
     197              :                 // Obtain the next two digits.
     198            0 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     199            0 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     200              : 
     201              :                 // Remaining 2 digits are all zero?
     202            0 :                 if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 100))
     203              :                 {
     204            0 :                     buffer += (3 + unsigned(buffer[3] > '0'));
     205              :                 }
     206              :                 else
     207              :                 {
     208              :                     // Obtain the last two digits.
     209            0 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     210            0 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
     211              : 
     212            0 :                     buffer += (5 + unsigned(buffer[5] > '0'));
     213              :                 }
     214              :             }
     215              :         }
     216          440 :         else if (s32 >= 100)
     217              :         {
     218              :             // 3 or 4 digits.
     219              :             // 42949673 = ceil(2^32 / 100)
     220           14 :             auto prod = s32 * std::uint64_t(42949673);
     221           14 :             const auto head_digits = std::uint32_t(prod >> 32);
     222              : 
     223              :             // If s32 is of 4 digits, increase the exponent by 3.
     224              :             // Otherwise, increase it by 2.
     225           14 :             exponent += (2 + int(head_digits >= 10));
     226              : 
     227              :             // Write the first digit and the decimal point.
     228           14 :             std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2);
     229              :             // This third character may be overwritten later but we don't care.
     230           14 :             buffer[2] = radix_table[head_digits * 2 + 1];
     231              : 
     232              :             // Remaining 2 digits are all zero?
     233           14 :             if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 100))
     234              :             {
     235              :                 // The number of characters actually written is 1 or 3, similarly to the case of
     236              :                 // 7 or 8 digits.
     237            0 :                 buffer += (1 + (unsigned(head_digits >= 10) & unsigned(buffer[2] > '0')) * 2);
     238              :             }
     239              :             else
     240              :             {
     241              :                 // At least one of the remaining 2 digits are nonzero.
     242              :                 // After this adjustment, now the first destination becomes buffer + 2.
     243           14 :                 buffer += unsigned(head_digits >= 10);
     244              : 
     245              :                 // Obtain the last two digits.
     246           14 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     247           14 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     248              : 
     249           14 :                 buffer += (3 + unsigned(buffer[3] > '0'));
     250              :             }
     251              :         }
     252              :         else
     253              :         {
     254              :             // 1 or 2 digits.
     255              :             // If s32 is of 2 digits, increase the exponent by 1.
     256          426 :             exponent += int(s32 >= 10);
     257              : 
     258              :             // Write the first digit and the decimal point.
     259          426 :             std::memcpy(buffer, radix_100_head_table + s32 * 2, 2);
     260              :             // This third character may be overwritten later but we don't care.
     261          426 :             buffer[2] = radix_table[s32 * 2 + 1];
     262              : 
     263              :             // The number of characters actually written is 1 or 3, similarly to the case of
     264              :             // 7 or 8 digits.
     265          426 :             buffer += (1 + (unsigned(s32 >= 10) & unsigned(buffer[2] > '0')) * 2);
     266              :         }
     267          440 :     }
     268              : 
     269          444 :     std::size_t dragon_box_print_chars(const std::uint64_t significand, int exponent, char* first, char* last) noexcept
     270              :     {
     271          444 :         BOOST_ASSERT( detail::max_number_chars >= std::size_t(last - first) );
     272              : 
     273          444 :         auto buffer = first;
     274              :         // Print significand by decomposing it into a 9-digit block and a 8-digit block.
     275              :         std::uint32_t first_block;
     276          444 :         std::uint32_t second_block {};
     277              :         bool no_second_block;
     278              : 
     279          444 :         if (significand >= 100000000)
     280              :         {
     281            4 :             first_block = std::uint32_t(significand / 100000000);
     282            4 :             second_block = std::uint32_t(significand) - first_block * 100000000;
     283            4 :             exponent += 8;
     284            4 :             no_second_block = (second_block == 0);
     285              :         }
     286              :         else
     287              :         {
     288          440 :             first_block = std::uint32_t(significand);
     289          440 :             no_second_block = true;
     290              :         }
     291              : 
     292          444 :         if (no_second_block)
     293              :         {
     294              :             print_9_digits(first_block, exponent, buffer);
     295              :         }
     296              :         else
     297              :         {
     298              :             // We proceed similarly to print_9_digits(), but since we do not need to remove
     299              :             // trailing zeros, the procedure is a bit simpler.
     300            4 :             if (first_block >= 100000000)
     301              :             {
     302              :                 // The input is of 17 digits, thus there should be no trailing zero at all.
     303              :                 // The first block is of 9 digits.
     304              :                 // 1441151882 = ceil(2^57 / 1'0000'0000) + 1
     305            1 :                 auto prod = first_block * std::uint64_t(1441151882);
     306            1 :                 prod >>= 25;
     307            1 :                 std::memcpy(buffer, radix_100_head_table + std::uint32_t(prod >> 32) * 2, 2);
     308            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     309            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     310            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     311            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
     312            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     313            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 6);
     314            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     315            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 8);
     316              : 
     317              :                 // The second block is of 8 digits.
     318              :                 // 281474978 = ceil(2^48 / 100'0000) + 1
     319            1 :                 prod = second_block * std::uint64_t(281474978);
     320            1 :                 prod >>= 16;
     321            1 :                 prod += 1;
     322            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 10);
     323            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     324            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 12);
     325            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     326            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 14);
     327            1 :                 prod = std::uint32_t(prod) * std::uint64_t(100);
     328            1 :                 print_2_digits(std::uint32_t(prod >> 32), buffer + 16);
     329              : 
     330            1 :                 exponent += 8;
     331            1 :                 buffer += 18;
     332              :             }
     333              :             else
     334              :             {
     335            3 :                 if (first_block >= 1000000)
     336              :                 {
     337              :                     // 7 or 8 digits.
     338              :                     // 281474978 = ceil(2^48 / 100'0000) + 1
     339            3 :                     auto prod = first_block * std::uint64_t(281474978);
     340            3 :                     prod >>= 16;
     341            3 :                     const auto head_digits = std::uint32_t(prod >> 32);
     342              : 
     343            3 :                     std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2);
     344            3 :                     buffer[2] = radix_table[head_digits * 2 + 1];
     345              : 
     346            3 :                     exponent += static_cast<int>(6 + unsigned(head_digits >= 10));
     347            3 :                     buffer += unsigned(head_digits >= 10);
     348              : 
     349              :                     // Print remaining 6 digits.
     350            3 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     351            3 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     352            3 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     353            3 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
     354            3 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     355            3 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 6);
     356              : 
     357            3 :                     buffer += 8;
     358              :                 }
     359            0 :                 else if (first_block >= 10000)
     360              :                 {
     361              :                     // 5 or 6 digits.
     362              :                     // 429497 = ceil(2^32 / 1'0000)
     363            0 :                     auto prod = first_block * std::uint64_t(429497);
     364            0 :                     const auto head_digits = std::uint32_t(prod >> 32);
     365              : 
     366            0 :                     std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2);
     367            0 :                     buffer[2] = radix_table[head_digits * 2 + 1];
     368              : 
     369            0 :                     exponent += static_cast<int>(4 + unsigned(head_digits >= 10));
     370            0 :                     buffer += unsigned(head_digits >= 10);
     371              : 
     372              :                     // Print remaining 4 digits.
     373            0 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     374            0 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     375            0 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     376            0 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
     377              : 
     378            0 :                     buffer += 6;
     379              :                 }
     380            0 :                 else if (first_block >= 100)
     381              :                 {
     382              :                     // 3 or 4 digits.
     383              :                     // 42949673 = ceil(2^32 / 100)
     384            0 :                     auto prod = first_block * std::uint64_t(42949673);
     385            0 :                     const auto head_digits = std::uint32_t(prod >> 32);
     386              : 
     387            0 :                     std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2);
     388            0 :                     buffer[2] = radix_table[head_digits * 2 + 1];
     389              : 
     390            0 :                     exponent += static_cast<int>(2 + unsigned(head_digits >= 10));
     391            0 :                     buffer += unsigned(head_digits >= 10);
     392              : 
     393              :                     // Print remaining 2 digits.
     394            0 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     395            0 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     396              : 
     397            0 :                     buffer += 4;
     398              :                 }
     399              :                 else
     400              :                 {
     401              :                     // 1 or 2 digits.
     402            0 :                     std::memcpy(buffer, radix_100_head_table + first_block * 2, 2);
     403            0 :                     buffer[2] = radix_table[first_block * 2 + 1];
     404              : 
     405            0 :                     exponent += (first_block >= 10);
     406            0 :                     buffer += (2 + unsigned(first_block >= 10));
     407              :                 }
     408              : 
     409              :                 // Next, print the second block.
     410              :                 // The second block is of 8 digits, but we may have trailing zeros.
     411              :                 // 281474978 = ceil(2^48 / 100'0000) + 1
     412            3 :                 auto prod = second_block * std::uint64_t(281474978);
     413            3 :                 prod >>= 16;
     414            3 :                 prod += 1;
     415            3 :                 print_2_digits(std::uint32_t(prod >> 32), buffer);
     416              : 
     417              :                 // Remaining 6 digits are all zero?
     418            3 :                 if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 1000000))
     419              :                 {
     420            0 :                     buffer += (1 + unsigned(buffer[1] > '0'));
     421              :                 }
     422              :                 else
     423              :                 {
     424              :                     // Obtain the next two digits.
     425            3 :                     prod = std::uint32_t(prod) * std::uint64_t(100);
     426            3 :                     print_2_digits(std::uint32_t(prod >> 32), buffer + 2);
     427              : 
     428              :                     // Remaining 4 digits are all zero?
     429            3 :                     if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 10000))
     430              :                     {
     431            0 :                         buffer += (3 + unsigned(buffer[3] > '0'));
     432              :                     }
     433              :                     else
     434              :                     {
     435              :                         // Obtain the next two digits.
     436            3 :                         prod = std::uint32_t(prod) * std::uint64_t(100);
     437            3 :                         print_2_digits(std::uint32_t(prod >> 32), buffer + 4);
     438              : 
     439              :                         // Remaining 2 digits are all zero?
     440            3 :                         if (std::uint32_t(prod) <= std::uint32_t((std::uint64_t(1) << 32) / 100))
     441              :                         {
     442            0 :                             buffer += (5 + unsigned(buffer[5] > '0'));
     443              :                         }
     444              :                         else
     445              :                         {
     446              :                             // Obtain the last two digits.
     447            3 :                             prod = std::uint32_t(prod) * std::uint64_t(100);
     448            3 :                             print_2_digits(std::uint32_t(prod >> 32), buffer + 6);
     449            3 :                             buffer += (7 + unsigned(buffer[7] > '0'));
     450              :                         }
     451              :                     }
     452              :                 }
     453              :             }
     454              :         }
     455          444 :         if (exponent < 0)
     456              :         {
     457           85 :             std::memcpy(buffer, "E-", 2);
     458           85 :             buffer += 2;
     459           85 :             exponent = -exponent;
     460              :         }
     461          359 :         else if (exponent == 0)
     462              :         {
     463          153 :             std::memcpy(buffer, "E0", 2);
     464          153 :             return 2 + (buffer - first);
     465              :         }
     466              :         else
     467              :         {
     468          206 :             std::memcpy(buffer, "E+", 2);
     469          206 :             buffer += 2;
     470              :         }
     471              : 
     472          291 :         if (exponent >= 100)
     473              :         {
     474              :             // d1 = exponent / 10; d2 = exponent % 10;
     475              :             // 6554 = ceil(2^16 / 10)
     476           22 :             auto prod = std::uint32_t(exponent) * std::uint32_t(6554);
     477           22 :             auto d1 = prod >> 16;
     478           22 :             prod = std::uint16_t(prod) * std::uint32_t(5); // * 10
     479           22 :             auto d2 = prod >> 15;                          // >> 16
     480           22 :             print_2_digits(d1, buffer);
     481           22 :             print_1_digit(d2, buffer + 2);
     482           22 :             buffer += 3;
     483              :         }
     484              :         else
     485              :         {
     486          269 :             print_2_digits(static_cast<std::uint32_t>(exponent), buffer);
     487          269 :             buffer += 2;
     488              :         }
     489              : 
     490          291 :         return buffer - first;
     491              :     }
     492              : 
     493              : #ifdef BOOST_MSVC
     494              : # pragma warning(pop)
     495              : #endif
     496              : 
     497              : } // namespace to_chars_detail
     498              : } // namespace detail
     499              : } // namespace json
     500              : } // namespace boost
        

Generated by: LCOV version 2.3