Skip to content

Commit 22c887c

Browse files
committed
Fix handling of explicit one in 80-bit long double
The code compared the computed ieeeMantissa (which includes the explicit leading one in the long double case) against 0, which is incorrect. Fixes #175.
1 parent 209531f commit 22c887c

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

ryu/generic_128.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ struct floating_decimal_128 generic_binary_to_decimal(
140140
// Step 2: Determine the interval of legal decimal representations.
141141
const uint128_t mv = 4 * m2;
142142
// Implicit bool -> int conversion. True is 1, false is 0.
143-
const uint32_t mmShift = (ieeeMantissa != 0) || (ieeeExponent == 0);
143+
const uint32_t mmShift =
144+
(ieeeMantissa != (explicitLeadingBit ? ONE << (mantissaBits - 1) : 0))
145+
|| (ieeeExponent == 0);
144146

145147
// Step 3: Convert to a decimal power base using 128-bit arithmetic.
146148
uint128_t vr, vp, vm;

ryu/tests/generic_128_test.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,19 @@ TEST(Generic128Test, long_double_to_fd128) {
342342
ASSERT_L2S("9.409340012568248E18", 9.409340012568248E18L);
343343
ASSERT_L2S("1.2345678E0", 1.2345678L);
344344
}
345+
346+
TEST(Generic128Test, regression_test_long_double) {
347+
// The binary 80-bit representation of this number has a mantissa that is a
348+
// one followed by zeros. This is a special case, because the next lower
349+
// number is closer to X than the next higher number, so it is possible that
350+
// we need to print more digits.
351+
// Before this test was added, the code incorrectly checked for an all-zeroes
352+
// mantissa in this case - the 80-bit format has an *explicit* leading one,
353+
// and the code did not take that into account.
354+
long double l = 1.10169395793497080013e-4927L;
355+
ASSERT_L2S("1.10169395793497080013E-4927", l);
356+
// Also check that the next higher and next lower number have *different*
357+
// decimal representations.
358+
ASSERT_L2S("1.1016939579349708003E-4927", nextafterl(l, INFINITY));
359+
ASSERT_L2S("1.1016939579349708001E-4927", nextafterl(l, -INFINITY));
360+
}

0 commit comments

Comments
 (0)