mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 03:33:33 +08:00
Fix strtod subnormal rounding (bug 30220)
As reported in bug 30220, the implementation of strtod-family
functions has a bug in the following case: the input string would,
with infinite exponent range, take one more bit to represent than is
available in the normal precision of the return type; the value
represented is in the subnormal range; and there are no nonzero bits
in the value, below those that can be represented in subnormal
precision, other than the least significant bit and possibly the
0.5ulp bit. In this case, round_and_return ends up discarding the
least significant bit.
Fix by saving that bit to merge into more_bits (it can't be merged in
at the time it's computed, because more_bits mustn't include this bit
in the case of after-rounding tininess detection checking if the
result is still subnormal when rounded to normal precision, so merging
this bit into more_bits needs to take place after that check).
Tested for x86_64.
(cherry picked from commit 457622c2fa
)
This commit is contained in:
parent
e06153665f
commit
d0c1792ad2
@ -222,6 +222,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
|
||||
|
||||
mp_size_t shift = MIN_EXP - 1 - exponent;
|
||||
bool is_tiny = true;
|
||||
bool old_half_bit = (round_limb & (((mp_limb_t) 1) << round_bit)) != 0;
|
||||
|
||||
more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
|
||||
if (shift == MANT_DIG)
|
||||
@ -292,6 +293,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
|
||||
round_bit = shift - 1;
|
||||
(void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
|
||||
}
|
||||
more_bits |= old_half_bit;
|
||||
/* This is a hook for the m68k long double format, where the
|
||||
exponent bias is the same for normalized and denormalized
|
||||
numbers. */
|
||||
|
@ -265,3 +265,15 @@
|
||||
1.000000000000000000000000000000000385185988877447170611195588516985463707620329643077639047987759113311767578125
|
||||
1.0000000000000000000000000000000001925929944387235853055977942584927318538101648215388195239938795566558837890625
|
||||
1.00000000000000000000000000000000009629649721936179265279889712924636592690508241076940976199693977832794189453125
|
||||
0x30000002222225p-1077
|
||||
0x0.7fffffffffffeap-1022
|
||||
0x0.7fffffffffffe9p-1022
|
||||
0x0.7ffffd4p-126
|
||||
0x0.7ffffffffffffffd4p-16382
|
||||
0x0.7ffffffffffffffd4p-16383
|
||||
0x0.7ffffffffffffffffffffffffffeap-16382
|
||||
0x0.7000004p-126
|
||||
0x0.70000000000002p-1022
|
||||
0x0.70000000000000004p-16382
|
||||
0x0.70000000000000004p-16383
|
||||
0x0.70000000000000000000000000002p-16382
|
||||
|
@ -15437,4 +15437,376 @@ static const struct test tests[] = {
|
||||
0x1p+0, false, false,
|
||||
0x1p+0, false, false,
|
||||
0x1.0000000000000000000000000001p+0, false, false),
|
||||
TEST ("0x30000002222225p-1077",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x1.800000111111p-1024, false, true,
|
||||
0x1.8000001111114p-1024, false, true,
|
||||
0x1.800000111111p-1024, false, true,
|
||||
0x1.8000001111114p-1024, false, true,
|
||||
true,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
true,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
false,
|
||||
0x1.800000111111p-1024, false, true,
|
||||
0x1.8000001111114p-1024, false, true,
|
||||
0x1.800000111111p-1024, false, true,
|
||||
0x1.8000001111114p-1024, false, true,
|
||||
true,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false,
|
||||
0x1.80000011111128p-1024, false, false),
|
||||
TEST ("0x0.7fffffffffffeap-1022",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
true,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
true,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
false,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
true,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false,
|
||||
0x1.ffffffffffffa8p-1024, false, false),
|
||||
TEST ("0x0.7fffffffffffe9p-1022",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
true,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
true,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
false,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
0x1.ffffffffffff8p-1024, false, true,
|
||||
0x1.ffffffffffffcp-1024, false, true,
|
||||
true,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false,
|
||||
0x1.ffffffffffffa4p-1024, false, false),
|
||||
TEST ("0x0.7ffffd4p-126",
|
||||
false,
|
||||
0x1.fffffp-128, false, true,
|
||||
0x1.fffff8p-128, false, true,
|
||||
0x1.fffffp-128, false, true,
|
||||
0x1.fffff8p-128, false, true,
|
||||
true,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
true,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
true,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
true,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
true,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false,
|
||||
0x1.fffff5p-128, false, false),
|
||||
TEST ("0x0.7ffffffffffffffd4p-16382",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0x1.fffffffffffffffp-16384, false, true,
|
||||
0x1.fffffffffffffff8p-16384, false, true,
|
||||
0x1.fffffffffffffffp-16384, false, true,
|
||||
0x1.fffffffffffffff8p-16384, false, true,
|
||||
false,
|
||||
0x1.fffffffffffffff4p-16384, false, true,
|
||||
0x1.fffffffffffffff4p-16384, false, true,
|
||||
0x1.fffffffffffffff4p-16384, false, true,
|
||||
0x1.fffffffffffffff8p-16384, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
true,
|
||||
0x1.fffffffffffffff5p-16384, false, false,
|
||||
0x1.fffffffffffffff5p-16384, false, false,
|
||||
0x1.fffffffffffffff5p-16384, false, false,
|
||||
0x1.fffffffffffffff5p-16384, false, false),
|
||||
TEST ("0x0.7ffffffffffffffd4p-16383",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0xf.ffffffffffffff8p-16388, false, true,
|
||||
0xf.ffffffffffffff8p-16388, false, true,
|
||||
0xf.ffffffffffffff8p-16388, false, true,
|
||||
0x1p-16384, false, true,
|
||||
false,
|
||||
0xf.ffffffffffffff8p-16388, false, true,
|
||||
0xf.ffffffffffffffcp-16388, false, true,
|
||||
0xf.ffffffffffffff8p-16388, false, true,
|
||||
0xf.ffffffffffffffcp-16388, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
true,
|
||||
0xf.ffffffffffffffa8p-16388, false, false,
|
||||
0xf.ffffffffffffffa8p-16388, false, false,
|
||||
0xf.ffffffffffffffa8p-16388, false, false,
|
||||
0xf.ffffffffffffffa8p-16388, false, false),
|
||||
TEST ("0x0.7ffffffffffffffffffffffffffeap-16382",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0x1.fffffffffffffff8p-16384, false, true,
|
||||
0x2p-16384, false, true,
|
||||
0x1.fffffffffffffff8p-16384, false, true,
|
||||
0x2p-16384, false, true,
|
||||
false,
|
||||
0x1.fffffffffffffffcp-16384, false, true,
|
||||
0x2p-16384, false, true,
|
||||
0x1.fffffffffffffffcp-16384, false, true,
|
||||
0x2p-16384, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0x1.fffffffffffffffffffffffffff8p-16384, false, true,
|
||||
0x1.fffffffffffffffffffffffffffcp-16384, false, true,
|
||||
0x1.fffffffffffffffffffffffffff8p-16384, false, true,
|
||||
0x1.fffffffffffffffffffffffffffcp-16384, false, true),
|
||||
TEST ("0x0.7000004p-126",
|
||||
false,
|
||||
0x1.cp-128, false, true,
|
||||
0x1.cp-128, false, true,
|
||||
0x1.cp-128, false, true,
|
||||
0x1.c00008p-128, false, true,
|
||||
true,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
true,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
true,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
true,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
true,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false,
|
||||
0x1.c00001p-128, false, false),
|
||||
TEST ("0x0.70000000000002p-1022",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x1.cp-1024, false, true,
|
||||
0x1.cp-1024, false, true,
|
||||
0x1.cp-1024, false, true,
|
||||
0x1.c000000000004p-1024, false, true,
|
||||
true,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
true,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
false,
|
||||
0x1.cp-1024, false, true,
|
||||
0x1.cp-1024, false, true,
|
||||
0x1.cp-1024, false, true,
|
||||
0x1.c000000000004p-1024, false, true,
|
||||
true,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false,
|
||||
0x1.c0000000000008p-1024, false, false),
|
||||
TEST ("0x0.70000000000000004p-16382",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.c000000000000008p-16384, false, true,
|
||||
false,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.c000000000000004p-16384, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
true,
|
||||
0x1.c000000000000001p-16384, false, false,
|
||||
0x1.c000000000000001p-16384, false, false,
|
||||
0x1.c000000000000001p-16384, false, false,
|
||||
0x1.c000000000000001p-16384, false, false),
|
||||
TEST ("0x0.70000000000000004p-16383",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0xep-16388, false, true,
|
||||
0xep-16388, false, true,
|
||||
0xep-16388, false, true,
|
||||
0xe.000000000000008p-16388, false, true,
|
||||
false,
|
||||
0xep-16388, false, true,
|
||||
0xep-16388, false, true,
|
||||
0xep-16388, false, true,
|
||||
0xe.000000000000004p-16388, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
true,
|
||||
0xe.0000000000000008p-16388, false, false,
|
||||
0xe.0000000000000008p-16388, false, false,
|
||||
0xe.0000000000000008p-16388, false, false,
|
||||
0xe.0000000000000008p-16388, false, false),
|
||||
TEST ("0x0.70000000000000000000000000002p-16382",
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x8p-152, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.c000000000000008p-16384, false, true,
|
||||
false,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.c000000000000004p-16384, false, true,
|
||||
false,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x0p+0, false, true,
|
||||
0x4p-1076, false, true,
|
||||
false,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.cp-16384, false, true,
|
||||
0x1.c000000000000000000000000004p-16384, false, true),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user