Skip to content

Commit d922b15

Browse files
committed
Merge singificand output
1 parent 8d4602d commit d922b15

File tree

1 file changed

+23
-34
lines changed

1 file changed

+23
-34
lines changed

zmij.cc

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -501,28 +501,24 @@ inline auto read8(char* buffer) noexcept -> uint64_t {
501501
return r;
502502
}
503503

504-
// Writes a significand consisting of up to 9 decimal digits (7-9 for normals)
505-
// and removes trailing zeros.
506-
auto write_significand9(char* buffer, uint32_t value, bool has9digits) noexcept
507-
-> char* {
508-
buffer = write_if(buffer, value / 100'000'000, has9digits);
509-
uint64_t bcd = to_bcd8(value % 100'000'000);
510-
write8(buffer, bcd + zeros);
511-
return buffer + count_trailing_nonzeros(bcd);
512-
}
513-
514-
// Writes a significand consisting of up to 17 decimal digits (16-17 for
515-
// normals) and removes trailing zeros. The significant digits start
516-
// from buffer[1]. buffer[0] may contain '0' after this function if
517-
// the significand has length 16.
518-
template <bool use_sse = ZMIJ_USE_SSE != 0>
519-
auto write_significand17(char* buffer, uint64_t value, bool has17digits,
520-
long long value_div10) noexcept -> char* {
504+
// Writes a significand and removes trailing zeros. value has up to 17 decimal
505+
// digits (16-17 for normals) for double (num_bits == 64) and up to 9 digits
506+
// (8-9 for normals) for float. The significant digits start from buffer[1].
507+
// buffer[0] may contain '0' after this function if the leading digit is zero.
508+
template <int num_bits, bool use_sse = ZMIJ_USE_SSE != 0 && num_bits == 64>
509+
auto write_significand(char* buffer, uint64_t value, bool extra_digit,
510+
long long value_div10) noexcept -> char* {
511+
if (num_bits == 32) {
512+
buffer = write_if(buffer, value / 100'000'000, extra_digit);
513+
uint64_t bcd = to_bcd8(value % 100'000'000);
514+
write8(buffer, bcd + zeros);
515+
return buffer + count_trailing_nonzeros(bcd);
516+
}
521517
if (!ZMIJ_USE_NEON && !use_sse) {
522518
// Digits/pairs of digits are denoted by letters: value = abbccddeeffgghhii.
523519
uint32_t abbccddee = uint32_t(value / 100'000'000);
524520
uint32_t ffgghhii = uint32_t(value % 100'000'000);
525-
buffer = write_if(buffer, abbccddee / 100'000'000, has17digits);
521+
buffer = write_if(buffer, abbccddee / 100'000'000, extra_digit);
526522
uint64_t bcd = to_bcd8(abbccddee % 100'000'000);
527523
write8(buffer, bcd + zeros);
528524
if (ffgghhii == 0) {
@@ -565,7 +561,7 @@ auto write_significand17(char* buffer, uint64_t value, bool has17digits,
565561
uint64_t a = uint64_t(umul128(abbccddee, c->mul_const) >> 90);
566562
uint64_t bbccddee = abbccddee - a * hundred_million;
567563

568-
buffer = write_if(buffer, a, has17digits);
564+
buffer = write_if(buffer, a, extra_digit);
569565

570566
uint64x1_t ffgghhii_bbccddee_64 = {(uint64_t(ffgghhii) << 32) | bbccddee};
571567
int32x2_t bbccddee_ffgghhii = vreinterpret_s32_u64(ffgghhii_bbccddee_64);
@@ -608,7 +604,7 @@ auto write_significand17(char* buffer, uint64_t value, bool has17digits,
608604
// We always write 17 digits into the buffer, but the first one can be zero.
609605
// buffer points to the second place in the output buffer to allow for the
610606
// insertion of the decimal point, so we can use the first place as scratch.
611-
buffer += has17digits - 1;
607+
buffer += extra_digit - 1;
612608
buffer[16] = char(last_digit + '0');
613609

614610
uint32_t abcdefgh = value_div10 / uint64_t(1e8);
@@ -881,11 +877,9 @@ auto write_fixed(char* buffer, uint64_t dec_sig, int dec_exp, bool extra_digit,
881877
long long dec_sig_div10) noexcept -> char* {
882878
if (dec_exp < 0) {
883879
char* point = buffer + 1;
884-
memcpy(buffer, "0.0000000", 8);
885-
buffer = num_bits == 64 ? write_significand17(buffer + 1 - dec_exp, dec_sig,
886-
extra_digit, dec_sig_div10)
887-
: write_significand9(buffer + 1 - dec_exp, dec_sig,
888-
extra_digit);
880+
memcpy(buffer, "0.000000", 8);
881+
buffer = write_significand<num_bits>(buffer + 1 - dec_exp, dec_sig,
882+
extra_digit, dec_sig_div10);
889883
if (ZMIJ_USE_SSE) *point = '.';
890884
*buffer = '\0';
891885
return buffer;
@@ -895,9 +889,8 @@ auto write_fixed(char* buffer, uint64_t dec_sig, int dec_exp, bool extra_digit,
895889
write8(buffer + (num_bits == 64 ? 16 : 7), 0);
896890

897891
char* start = buffer;
898-
buffer = num_bits == 64 ? write_significand17<false>(buffer, dec_sig, extra_digit,
899-
dec_sig_div10)
900-
: write_significand9(buffer, dec_sig, extra_digit);
892+
buffer = write_significand<num_bits, false>(buffer, dec_sig, extra_digit,
893+
dec_sig_div10);
901894

902895
// Branchless move to make space for the '.' without OOB accesses.
903896
char* part1 = start + dec_exp + (dec_exp < 2);
@@ -989,12 +982,8 @@ auto write(Float value, char* buffer) noexcept -> char* {
989982
dec.sig_div10);
990983
}
991984
char* start = buffer;
992-
if (traits::num_bits == 64) {
993-
buffer =
994-
write_significand17(buffer + 1, dec.sig, extra_digit, dec.sig_div10);
995-
} else {
996-
buffer = write_significand9(buffer + 1, dec.sig, extra_digit);
997-
}
985+
buffer = write_significand<traits::num_bits>(buffer + 1, dec.sig, extra_digit,
986+
dec.sig_div10);
998987
start[0] = start[1];
999988
start[1] = '.';
1000989
buffer -= (buffer - 1 == start + 1); // Remove trailing point.

0 commit comments

Comments
 (0)