Skip to content

Commit 5bd34e0

Browse files
[libc] Fix Off By One Errors In Printf Long Double (#66957)
Two major off-by-one errors are fixed in this patch. The first is in float_to_string.h with length_for_num, which wasn't accounting for the implicit leading bit when calculating the length of a number, causing a missing digit on 80 bit float max. The other off-by-one is the ryu_long_double_constants.h (a.k.a the Mega Table) not having any entries for the last POW10_OFFSET in POW10_SPLIT. This was also found on 80 bit float max. Finally, the integer calculation mode was using a slightly too short integer, again on 80 bit float max, not accounting for the mantissa width. All of these are fixed in this patch.
1 parent 9a99944 commit 5bd34e0

File tree

4 files changed

+638
-5
lines changed

4 files changed

+638
-5
lines changed

libc/src/__support/float_to_string.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ LIBC_INLINE constexpr uint32_t ceil_log10_pow2(const uint32_t e) {
157157
LIBC_INLINE constexpr uint32_t length_for_num(const uint32_t idx,
158158
const uint32_t mantissa_width) {
159159
//+8 to round up when dividing by 9
160-
return (ceil_log10_pow2(idx) + ceil_log10_pow2(mantissa_width) +
160+
return (ceil_log10_pow2(idx) + ceil_log10_pow2(mantissa_width + 1) +
161161
(BLOCK_SIZE - 1)) /
162162
BLOCK_SIZE;
163163
// return (ceil_log10_pow2(16 * idx + mantissa_width) + 8) / 9;
@@ -666,7 +666,7 @@ FloatToString<long double>::get_positive_block(int block_index) {
666666
// ----------------------------- INT CALC MODE -----------------------------
667667
const int32_t SHIFT_CONST = CALC_SHIFT_CONST;
668668
const uint64_t MAX_POW_2_SIZE =
669-
exponent + CALC_SHIFT_CONST - (BLOCK_SIZE * block_index);
669+
pos_exp + CALC_SHIFT_CONST - (BLOCK_SIZE * block_index);
670670
const uint64_t MAX_POW_5_SIZE =
671671
internal::log2_pow5(BLOCK_SIZE * block_index);
672672
const uint64_t MAX_INT_SIZE =
@@ -680,8 +680,10 @@ FloatToString<long double>::get_positive_block(int block_index) {
680680
val = internal::get_table_positive<4096>(pos_exp, block_index);
681681
} else if (MAX_INT_SIZE < 8192) {
682682
val = internal::get_table_positive<8192>(pos_exp, block_index);
683-
} else {
683+
} else if (MAX_INT_SIZE < 16384) {
684684
val = internal::get_table_positive<16384>(pos_exp, block_index);
685+
} else {
686+
val = internal::get_table_positive<16384 + 128>(pos_exp, block_index);
685687
}
686688
#endif
687689
const uint32_t shift_amount = SHIFT_CONST + pos_exp - exponent;

0 commit comments

Comments
 (0)