mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Fix strtof decimal rounding close to half least subnormal (bug 18247).
Bug 18247 is an off-by-one error in strtof's determination of a decimal exponent such that any value with that decimal exponent is at most half the least subnormal and so the appropriate underflowing value for the rounding mode can be determined with no multiple-precision computations. (Whether the value is in fact safe despite the off-by-one depends on the floating-point format in question. It's wrong for float and for m68k ldbl-96 but not for other supported formats.) This patch corrects the computation of the exponent in question to be safe in general, adding a comment explaining the new computation. Tested for x86_64. [BZ #18247] * stdlib/strtod_l.c (____STRTOF_INTERNAL): Decrease minimum decimal exponent by 1. * stdlib/tst-strtod-round-data: Add more tests. * stdlib/tst-strtod-round.c (tests): Regenerated.
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
2015-04-10 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
|
[BZ #18247]
|
||||||
|
* stdlib/strtod_l.c (____STRTOF_INTERNAL): Decrease minimum
|
||||||
|
decimal exponent by 1.
|
||||||
|
* stdlib/tst-strtod-round-data: Add more tests.
|
||||||
|
* stdlib/tst-strtod-round.c (tests): Regenerated.
|
||||||
|
|
||||||
2015-04-09 Joseph Myers <joseph@codesourcery.com>
|
2015-04-09 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* math/auto-libm-test-in: Add more tests of clog and clog10.
|
* math/auto-libm-test-in: Add more tests of clog and clog10.
|
||||||
|
2
NEWS
2
NEWS
@ -16,7 +16,7 @@ Version 2.22
|
|||||||
17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, 18029,
|
17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, 18029,
|
||||||
18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, 18068,
|
18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, 18068,
|
||||||
18080, 18093, 18100, 18104, 18110, 18111, 18128, 18138, 18185, 18197,
|
18080, 18093, 18100, 18104, 18110, 18111, 18128, 18138, 18185, 18197,
|
||||||
18210, 18211.
|
18210, 18211, 18247.
|
||||||
|
|
||||||
* A powerpc and powerpc64 optimization for TLS, similar to TLS descriptors
|
* A powerpc and powerpc64 optimization for TLS, similar to TLS descriptors
|
||||||
for LD and GD on x86 and x86-64, has been implemented. You will need
|
for LD and GD on x86 and x86-64, has been implemented. You will need
|
||||||
|
@ -1189,7 +1189,16 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
|
|||||||
if (__glibc_unlikely (exponent > MAX_10_EXP + 1 - (intmax_t) int_no))
|
if (__glibc_unlikely (exponent > MAX_10_EXP + 1 - (intmax_t) int_no))
|
||||||
return overflow_value (negative);
|
return overflow_value (negative);
|
||||||
|
|
||||||
if (__glibc_unlikely (exponent < MIN_10_EXP - (DIG + 1)))
|
/* 10^(MIN_10_EXP-1) is not normal. Thus, 10^(MIN_10_EXP-1) /
|
||||||
|
2^MANT_DIG is below half the least subnormal, so anything with a
|
||||||
|
base-10 exponent less than the base-10 exponent (which is
|
||||||
|
MIN_10_EXP - 1 - ceil(MANT_DIG*log10(2))) of that value
|
||||||
|
underflows. DIG is floor((MANT_DIG-1)log10(2)), so an exponent
|
||||||
|
below MIN_10_EXP - (DIG + 3) underflows. But EXPONENT is
|
||||||
|
actually an exponent multiplied only by a fractional part, not an
|
||||||
|
integer part, so an exponent below MIN_10_EXP - (DIG + 2)
|
||||||
|
underflows. */
|
||||||
|
if (__glibc_unlikely (exponent < MIN_10_EXP - (DIG + 2)))
|
||||||
return underflow_value (negative);
|
return underflow_value (negative);
|
||||||
|
|
||||||
if (int_no > 0)
|
if (int_no > 0)
|
||||||
@ -1356,7 +1365,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
|
|||||||
|
|
||||||
assert (dig_no > int_no
|
assert (dig_no > int_no
|
||||||
&& exponent <= 0
|
&& exponent <= 0
|
||||||
&& exponent >= MIN_10_EXP - (DIG + 1));
|
&& exponent >= MIN_10_EXP - (DIG + 2));
|
||||||
|
|
||||||
/* We need to compute MANT_DIG - BITS fractional bits that lie
|
/* We need to compute MANT_DIG - BITS fractional bits that lie
|
||||||
within the mantissa of the result, the following bit for
|
within the mantissa of the result, the following bit for
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user