@@ -504,12 +504,10 @@ inline auto read8(char* buffer) noexcept -> uint64_t {
504504// and removes trailing zeros.
505505auto write_significand9 (char * buffer, uint32_t value, bool has9digits) noexcept
506506 -> char* {
507- char * start = buffer;
508507 buffer = write_if (buffer, value / 100'000'000 , has9digits);
509508 uint64_t bcd = to_bcd8 (value % 100'000'000 );
510509 write8 (buffer, bcd | zeros);
511- buffer += count_trailing_nonzeros (bcd);
512- return buffer - int (buffer - start == 1 );
510+ return buffer + count_trailing_nonzeros (bcd);
513511}
514512
515513// Writes a significand consisting of up to 17 decimal digits (16-17 for
@@ -870,29 +868,38 @@ ZMIJ_INLINE auto to_decimal_normal(UInt bin_sig, int64_t raw_exp,
870868 return to_decimal_schubfach (bin_sig, bin_exp, regular);
871869}
872870
871+ template <int num_bits>
873872auto write_fixed (char * buffer, uint64_t dec_sig, int dec_exp, bool has17digits,
874873 long long dec_sig_div10) noexcept -> char* {
875874 if (dec_exp < 0 ) {
876875 memcpy (buffer, " 0.0000000" , 8 );
877- buffer = write_significand17 (buffer + 1 - dec_exp, dec_sig, has17digits,
878- dec_sig_div10);
876+ buffer = num_bits == 64 ? write_significand17 (buffer + 1 - dec_exp, dec_sig,
877+ has17digits, dec_sig_div10)
878+ : write_significand9 (buffer + 1 - dec_exp, dec_sig,
879+ has17digits);
879880 *buffer = ' \0 ' ;
880881 return buffer;
881882 }
882883
883884 // Avoid reading uninitialized memory (would be unnecessary in asm).
884- write8 (buffer + 16 , 0 );
885+ write8 (buffer + (num_bits == 64 ? 16 : 7 ) , 0 );
885886
886887 char * start = buffer;
887- buffer = write_significand17 (buffer, dec_sig, has17digits, dec_sig_div10);
888+ buffer = num_bits == 64 ? write_significand17 (buffer, dec_sig, has17digits,
889+ dec_sig_div10)
890+ : write_significand9 (buffer, dec_sig, has17digits);
888891
889892 // Branchless move to make space for the '.' without OOB accesses.
890893 char * part1 = start + dec_exp + (dec_exp < 2 );
891894 char * part2 = part1 + (dec_exp < 2 ) + (dec_exp < 9 ? 7 : 0 );
892- uint64_t value1 = read8 (part1);
893- uint64_t value2 = read8 (part2);
894- write8 (part1 + 1 , value1);
895- write8 (part2 + 1 , value2);
895+ if (num_bits == 64 ) {
896+ uint64_t value1 = read8 (part1);
897+ uint64_t value2 = read8 (part2);
898+ write8 (part1 + 1 , value1);
899+ write8 (part2 + 1 , value2);
900+ } else {
901+ write8 (part1 + 1 , read8 (part1));
902+ }
896903
897904 char * dot = start + dec_exp + 1 ;
898905 *dot = ' .' ;
@@ -958,22 +965,23 @@ auto write(Float value, char* buffer) noexcept -> char* {
958965 bin_sig != 0 );
959966 }
960967 int dec_exp = dec.exp ;
961- constexpr uint64_t threshold = uint64_t (traits::num_bits == 64 ? 1e16 : 1e8 );
962- bool extra_digit = dec.sig >= threshold;
968+ bool extra_digit = dec.sig >= uint64_t (traits::num_bits == 64 ? 1e16 : 1e8 );
963969 dec_exp += traits::max_digits10 - 2 + extra_digit;
970+ if (traits::num_bits == 32 && dec.sig < uint32_t (1e7 )) [[ZMIJ_UNLIKELY]] {
971+ dec.sig *= 10 ;
972+ --dec_exp;
973+ }
964974
965975 // Write significand.
976+ if (dec_exp >= -4 && dec_exp < compute_dec_exp (traits::digits + 1 , true )) {
977+ return write_fixed<traits::num_bits>(buffer, dec.sig , dec_exp, extra_digit,
978+ dec.sig_div10 );
979+ }
966980 char * start = buffer;
967981 if (traits::num_bits == 64 ) {
968- if (dec_exp >= -4 && dec_exp < compute_dec_exp (traits::digits + 1 , true ))
969- return write_fixed (buffer, dec.sig , dec_exp, extra_digit, dec.sig_div10 );
970982 buffer =
971983 write_significand17 (buffer + 1 , dec.sig , extra_digit, dec.sig_div10 );
972984 } else {
973- if (dec.sig < uint32_t (1e7 )) [[ZMIJ_UNLIKELY]] {
974- dec.sig *= 10 ;
975- --dec_exp;
976- }
977985 buffer = write_significand9 (buffer + 1 , dec.sig , extra_digit);
978986 }
979987 start[0 ] = start[1 ];
0 commit comments