mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 19:00:07 +00:00
Fix fma overflow results outside round-to-nearest mode (bug 14797).
This commit is contained in:
parent
b830319d49
commit
a0c2940d67
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
2012-11-04 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #14797]
|
||||
* sysdeps/ieee754/dbl-64/s_fma.c (__fma): Compute cases that
|
||||
definitely overflow as x * y not x * y + z.
|
||||
* sysdeps/ieee754/ldbl-128/s_fmal.c (__fmal): Likewise.
|
||||
* sysdeps/ieee754/ldbl-96/s_fmal.c (__fmal): Likewise.
|
||||
* math/libm-test.inc (fma_test): Add more tests.
|
||||
(fma_test_towardzero): Likewise.
|
||||
(fma_test_downward): Likewise.
|
||||
(fma_test_upward): Likewise.
|
||||
|
||||
2012-11-04 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
[BZ #157]
|
||||
|
2
NEWS
2
NEWS
@ -18,7 +18,7 @@ Version 2.17
|
||||
14530, 14532, 14538, 14543, 14544, 14545, 14557, 14562, 14568, 14576,
|
||||
14579, 14583, 14587, 14595, 14602, 14610, 14621, 14638, 14645, 14648,
|
||||
14652, 14660, 14661, 14669, 14683, 14694, 14716, 14743, 14767, 14783,
|
||||
14784, 14785, 14796.
|
||||
14784, 14785, 14796, 14797.
|
||||
|
||||
* Support for STT_GNU_IFUNC symbols added for s390 and s390x.
|
||||
Optimized versions of memcpy, memset, and memcmp added for System z10 and
|
||||
|
@ -4617,6 +4617,15 @@ fma_test (void)
|
||||
TEST_fff_f (fma, -min_value, -min_value, plus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -min_value, -min_value, minus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||
|
||||
TEST_fff_f (fma, max_value, max_value, min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, max_value, -min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, -min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, -min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, -min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
|
||||
#if defined (TEST_FLOAT) && FLT_MANT_DIG == 24
|
||||
TEST_fff_f (fma, 0x1.7ff8p+13, 0x1.000002p+0, 0x1.ffffp-24, 0x1.7ff802p+13);
|
||||
TEST_fff_f (fma, 0x1.fffp+0, 0x1.00001p+0, -0x1.fffp+0, 0x1.fffp-20);
|
||||
@ -4837,6 +4846,15 @@ fma_test_towardzero (void)
|
||||
TEST_fff_f (fma, -min_value, -min_value, plus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -min_value, -min_value, minus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||
|
||||
TEST_fff_f (fma, max_value, max_value, min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, max_value, -min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, -min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, -min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, -min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
|
||||
#if defined (TEST_FLOAT) && FLT_MANT_DIG == 24
|
||||
TEST_fff_f (fma, 0x1.4p-126, 0x1.000004p-1, 0x1p-128, 0x1.c00004p-127, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -0x1.4p-126, 0x1.000004p-1, -0x1p-128, -0x1.c00004p-127, UNDERFLOW_EXCEPTION);
|
||||
@ -5014,6 +5032,15 @@ fma_test_downward (void)
|
||||
TEST_fff_f (fma, -min_value, -min_value, plus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -min_value, -min_value, minus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||
|
||||
TEST_fff_f (fma, max_value, max_value, min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, max_value, -min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, -min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, -min_value, minus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, -min_value, max_value, OVERFLOW_EXCEPTION);
|
||||
|
||||
#if defined (TEST_FLOAT) && FLT_MANT_DIG == 24
|
||||
TEST_fff_f (fma, 0x1.4p-126, 0x1.000004p-1, 0x1p-128, 0x1.c00004p-127, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -0x1.4p-126, 0x1.000004p-1, -0x1p-128, -0x1.c00008p-127, UNDERFLOW_EXCEPTION);
|
||||
@ -5191,6 +5218,15 @@ fma_test_upward (void)
|
||||
TEST_fff_f (fma, -min_value, -min_value, plus_zero, min_subnorm_value, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -min_value, -min_value, minus_zero, min_subnorm_value, UNDERFLOW_EXCEPTION);
|
||||
|
||||
TEST_fff_f (fma, max_value, max_value, min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, max_value, -min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, max_value, -max_value, -min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, max_value, -min_value, -max_value, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -max_value, -max_value, -min_value, plus_infty, OVERFLOW_EXCEPTION);
|
||||
|
||||
#if defined (TEST_FLOAT) && FLT_MANT_DIG == 24
|
||||
TEST_fff_f (fma, 0x1.4p-126, 0x1.000004p-1, 0x1p-128, 0x1.c00008p-127, UNDERFLOW_EXCEPTION);
|
||||
TEST_fff_f (fma, -0x1.4p-126, 0x1.000004p-1, -0x1p-128, -0x1.c00004p-127, UNDERFLOW_EXCEPTION);
|
||||
|
@ -55,16 +55,17 @@ __fma (double x, double y, double z)
|
||||
underflows to 0. */
|
||||
if (z == 0 && x != 0 && y != 0)
|
||||
return x * y;
|
||||
/* If x or y or z is Inf/NaN, or if fma will certainly overflow,
|
||||
or if x * y is zero, compute as x * y + z. */
|
||||
/* If x or y or z is Inf/NaN, or if x * y is zero, compute as
|
||||
x * y + z. */
|
||||
if (u.ieee.exponent == 0x7ff
|
||||
|| v.ieee.exponent == 0x7ff
|
||||
|| w.ieee.exponent == 0x7ff
|
||||
|| u.ieee.exponent + v.ieee.exponent
|
||||
> 0x7ff + IEEE754_DOUBLE_BIAS
|
||||
|| x == 0
|
||||
|| y == 0)
|
||||
return x * y + z;
|
||||
/* If fma will certainly overflow, compute as x * y. */
|
||||
if (u.ieee.exponent + v.ieee.exponent > 0x7ff + IEEE754_DOUBLE_BIAS)
|
||||
return x * y;
|
||||
/* If x * y is less than 1/4 of DBL_DENORM_MIN, neither the
|
||||
result nor whether there is underflow depends on its exact
|
||||
value, only on its sign. */
|
||||
|
@ -56,16 +56,18 @@ __fmal (long double x, long double y, long double z)
|
||||
underflows to 0. */
|
||||
if (z == 0 && x != 0 && y != 0)
|
||||
return x * y;
|
||||
/* If x or y or z is Inf/NaN, or if fma will certainly overflow,
|
||||
or if x * y is zero, compute as x * y + z. */
|
||||
/* If x or y or z is Inf/NaN, or if x * y is zero, compute as
|
||||
x * y + z. */
|
||||
if (u.ieee.exponent == 0x7fff
|
||||
|| v.ieee.exponent == 0x7fff
|
||||
|| w.ieee.exponent == 0x7fff
|
||||
|| u.ieee.exponent + v.ieee.exponent
|
||||
> 0x7fff + IEEE854_LONG_DOUBLE_BIAS
|
||||
|| x == 0
|
||||
|| y == 0)
|
||||
return x * y + z;
|
||||
/* If fma will certainly overflow, compute as x * y. */
|
||||
if (u.ieee.exponent + v.ieee.exponent
|
||||
> 0x7fff + IEEE854_LONG_DOUBLE_BIAS)
|
||||
return x * y;
|
||||
/* If x * y is less than 1/4 of LDBL_DENORM_MIN, neither the
|
||||
result nor whether there is underflow depends on its exact
|
||||
value, only on its sign. */
|
||||
|
@ -56,16 +56,18 @@ __fmal (long double x, long double y, long double z)
|
||||
underflows to 0. */
|
||||
if (z == 0 && x != 0 && y != 0)
|
||||
return x * y;
|
||||
/* If x or y or z is Inf/NaN, or if fma will certainly overflow,
|
||||
or if x * y is zero, compute as x * y + z. */
|
||||
/* If x or y or z is Inf/NaN, or if x * y is zero, compute as
|
||||
x * y + z. */
|
||||
if (u.ieee.exponent == 0x7fff
|
||||
|| v.ieee.exponent == 0x7fff
|
||||
|| w.ieee.exponent == 0x7fff
|
||||
|| u.ieee.exponent + v.ieee.exponent
|
||||
> 0x7fff + IEEE854_LONG_DOUBLE_BIAS
|
||||
|| x == 0
|
||||
|| y == 0)
|
||||
return x * y + z;
|
||||
/* If fma will certainly overflow, compute as x * y. */
|
||||
if (u.ieee.exponent + v.ieee.exponent
|
||||
> 0x7fff + IEEE854_LONG_DOUBLE_BIAS)
|
||||
return x * y;
|
||||
/* If x * y is less than 1/4 of LDBL_DENORM_MIN, neither the
|
||||
result nor whether there is underflow depends on its exact
|
||||
value, only on its sign. */
|
||||
|
Loading…
Reference in New Issue
Block a user