This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Fix strtod rounding of half the least subnormal (bug 16151)
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: <libc-alpha at sourceware dot org>
- Date: Mon, 11 Nov 2013 18:45:43 +0000
- Subject: Fix strtod rounding of half the least subnormal (bug 16151)
- Authentication-results: sourceware.org; auth=none
This patch fixes bug 16151, incorrect strtod handling of inputs that
are exactly plus or minus half the least subnormal, for
round-to-nearest. In this case, the caller of round_and_return
computes a MANT_DIG-bit mantissa, all of which needs shifting out, and
the computation of whether any bits were set in that mantissa wrongly
tests the high-order limb (this limb gets used as round_limb, so the
relevant subset of bits in it get handled later, so this loop can
completely ignore it when setting more_bits). This patch makes the
required adjustment to the loop; the other shift case with such a loop
is already correct. Tested x86_64 and x86.
2013-11-11 Joseph Myers <joseph@codesourcery.com>
[BZ #16151]
* stdlib/strtod_l.c (round_and_return): Do not consider
retval[RETURN_LIBM_SIZE - 1] when determining more_bits for an
exponent one less than half the least subnormal exponent.
* stdlib/test-strtod-round-data: Add more tests.
* stdlib/tst-strtod-round.c (tests): Regenerated.
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index 90541cd..c1c5c0d 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -228,7 +228,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
round_limb = retval[RETURN_LIMB_SIZE - 1];
round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
- for (i = 0; i < RETURN_LIMB_SIZE; ++i)
+ for (i = 0; i < RETURN_LIMB_SIZE - 1; ++i)
more_bits |= retval[i] != 0;
MPN_ZERO (retval, RETURN_LIMB_SIZE);
}
diff --git a/stdlib/tst-strtod-round-data b/stdlib/tst-strtod-round-data
index 86d460e..a6c3767 100644
--- a/stdlib/tst-strtod-round-data
+++ b/stdlib/tst-strtod-round-data
@@ -109,3 +109,11 @@
-0x0.7p-1074
-0x0.7p-16445
-0x0.7p-16494
+0x1p-150
+0x1p-1075
+0x1p-16446
+0x1p-16495
+-0x1p-150
+-0x1p-1075
+-0x1p-16446
+-0x1p-16495
diff --git a/stdlib/tst-strtod-round.c b/stdlib/tst-strtod-round.c
index 9a44026..e7aaed1 100644
--- a/stdlib/tst-strtod-round.c
+++ b/stdlib/tst-strtod-round.c
@@ -7535,6 +7535,294 @@ static const struct test tests[] = {
-0x0p+0L,
-0x0p+0L,
-0x0p+0L),
+ TEST ("0x1p-150",
+ false,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x8p-152f,
+ true,
+ 0x4p-152,
+ 0x4p-152,
+ 0x4p-152,
+ 0x4p-152,
+ true,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ true,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ true,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ true,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ true,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L,
+ 0x4p-152L),
+ TEST ("0x1p-1075",
+ false,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x8p-152f,
+ false,
+ 0x0p+0,
+ 0x0p+0,
+ 0x0p+0,
+ 0x4p-1076,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-1076L,
+ true,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ true,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-1076L,
+ true,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ 0x2p-1076L,
+ 0x2p-1076L),
+ TEST ("0x1p-16446",
+ false,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x8p-152f,
+ false,
+ 0x0p+0,
+ 0x0p+0,
+ 0x0p+0,
+ 0x4p-1076,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-1076L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x8p-16448L,
+ true,
+ 0x4p-16448L,
+ 0x4p-16448L,
+ 0x4p-16448L,
+ 0x4p-16448L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-1076L,
+ true,
+ 0x4p-16448L,
+ 0x4p-16448L,
+ 0x4p-16448L,
+ 0x4p-16448L),
+ TEST ("0x1p-16495",
+ false,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x0p+0f,
+ 0x8p-152f,
+ false,
+ 0x0p+0,
+ 0x0p+0,
+ 0x0p+0,
+ 0x4p-1076,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-1076L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x8p-16448L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-16448L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-1076L,
+ false,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x0p+0L,
+ 0x4p-16496L),
+ TEST ("-0x1p-150",
+ false,
+ -0x8p-152f,
+ -0x0p+0f,
+ -0x0p+0f,
+ -0x0p+0f,
+ true,
+ -0x4p-152,
+ -0x4p-152,
+ -0x4p-152,
+ -0x4p-152,
+ true,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ true,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ true,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ true,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ true,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L,
+ -0x4p-152L),
+ TEST ("-0x1p-1075",
+ false,
+ -0x8p-152f,
+ -0x0p+0f,
+ -0x0p+0f,
+ -0x0p+0f,
+ false,
+ -0x4p-1076,
+ -0x0p+0,
+ -0x0p+0,
+ -0x0p+0,
+ false,
+ -0x4p-1076L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ true,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ true,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ false,
+ -0x4p-1076L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ true,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ -0x2p-1076L,
+ -0x2p-1076L),
+ TEST ("-0x1p-16446",
+ false,
+ -0x8p-152f,
+ -0x0p+0f,
+ -0x0p+0f,
+ -0x0p+0f,
+ false,
+ -0x4p-1076,
+ -0x0p+0,
+ -0x0p+0,
+ -0x0p+0,
+ false,
+ -0x4p-1076L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ false,
+ -0x8p-16448L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ true,
+ -0x4p-16448L,
+ -0x4p-16448L,
+ -0x4p-16448L,
+ -0x4p-16448L,
+ false,
+ -0x4p-1076L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ true,
+ -0x4p-16448L,
+ -0x4p-16448L,
+ -0x4p-16448L,
+ -0x4p-16448L),
+ TEST ("-0x1p-16495",
+ false,
+ -0x8p-152f,
+ -0x0p+0f,
+ -0x0p+0f,
+ -0x0p+0f,
+ false,
+ -0x4p-1076,
+ -0x0p+0,
+ -0x0p+0,
+ -0x0p+0,
+ false,
+ -0x4p-1076L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ false,
+ -0x8p-16448L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ false,
+ -0x4p-16448L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ false,
+ -0x4p-1076L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L,
+ false,
+ -0x4p-16496L,
+ -0x0p+0L,
+ -0x0p+0L,
+ -0x0p+0L),
};
static int
--
Joseph S. Myers
joseph@codesourcery.com