Skip to content

Commit bfcfc2a

Browse files
[libc] Fix typo in long double negative block (#68243)
The long double version of float to string's get_negative_block had a bug in table mode. In table mode, one of the tables is named "MIN_BLOCK_2" and it stores the number of blocks that are all zeroes before the digits start for a given index. The check for long doubles was incorrectly "block_index <= MIN_BLOCK_2[idx]" when it should be "block_index < MIN_BLOCK_2[idx]" (without the equal sign). This bug caused an off-by-one error for some long double values. This patch fixes the bug and adds tests to ensure it doesn't regress.
1 parent 7539bcf commit bfcfc2a

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

libc/src/__support/float_to_string.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ FloatToString<long double>::get_negative_block(int block_index) {
708708
const int32_t SHIFT_CONST = TABLE_SHIFT_CONST;
709709

710710
// if the requested block is zero
711-
if (block_index <= MIN_BLOCK_2[idx]) {
711+
if (block_index < MIN_BLOCK_2[idx]) {
712712
return 0;
713713
}
714714
const uint32_t p = POW10_OFFSET_2[idx] + block_index - MIN_BLOCK_2[idx];

libc/test/src/stdio/sprintf_test.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2433,6 +2433,9 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
24332433
written = LIBC_NAMESPACE::sprintf(buff, "%g", 9999999000000.00);
24342434
ASSERT_STREQ_LEN(written, buff, "1e+13");
24352435

2436+
written = LIBC_NAMESPACE::sprintf(buff, "%g", 0xa.aaaaaaaaaaaaaabp-7);
2437+
ASSERT_STREQ_LEN(written, buff, "0.0833333");
2438+
24362439
// Simple Subnormal Tests.
24372440

24382441
written = LIBC_NAMESPACE::sprintf(buff, "%g", 0x1.0p-1027);
@@ -2457,9 +2460,16 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
24572460

24582461
// Length Modifier Tests.
24592462

2463+
#if defined(SPECIAL_X86_LONG_DOUBLE)
2464+
24602465
written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xf.fffffffffffffffp+16380L);
24612466
ASSERT_STREQ_LEN(written, buff, "1.18973e+4932");
24622467

2468+
written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xa.aaaaaaaaaaaaaabp-7L);
2469+
ASSERT_STREQ_LEN(written, buff, "0.0833333");
2470+
2471+
#endif // SPECIAL_X86_LONG_DOUBLE
2472+
24632473
// TODO: Uncomment the below tests after long double support is added
24642474
/*
24652475
written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L);
@@ -2757,6 +2767,15 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
27572767
written = LIBC_NAMESPACE::sprintf(buff, "%.10g", 0x1.0p-1074);
27582768
ASSERT_STREQ_LEN(written, buff, "4.940656458e-324");
27592769

2770+
#if defined(SPECIAL_X86_LONG_DOUBLE)
2771+
2772+
written = LIBC_NAMESPACE::sprintf(buff, "%.60Lg", 0xa.aaaaaaaaaaaaaabp-7L);
2773+
ASSERT_STREQ_LEN(
2774+
written, buff,
2775+
"0.0833333333333333333355920878593448009041821933351457118988037");
2776+
2777+
#endif // SPECIAL_X86_LONG_DOUBLE
2778+
27602779
// Long double precision tests.
27612780
// These are currently commented out because they require long double support
27622781
// that isn't ready yet.

0 commit comments

Comments
 (0)