mirror of
https://sourceware.org/git/glibc.git
synced 2025-09-04 03:22:14 +03:00
Fix fma overflow results outside round-to-nearest mode (bug 14797).
This commit is contained in:
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>
|
2012-11-04 Thomas Schwinge <thomas@codesourcery.com>
|
||||||
|
|
||||||
[BZ #157]
|
[BZ #157]
|
||||||
|
2
NEWS
2
NEWS
@@ -18,7 +18,7 @@ Version 2.17
|
|||||||
14530, 14532, 14538, 14543, 14544, 14545, 14557, 14562, 14568, 14576,
|
14530, 14532, 14538, 14543, 14544, 14545, 14557, 14562, 14568, 14576,
|
||||||
14579, 14583, 14587, 14595, 14602, 14610, 14621, 14638, 14645, 14648,
|
14579, 14583, 14587, 14595, 14602, 14610, 14621, 14638, 14645, 14648,
|
||||||
14652, 14660, 14661, 14669, 14683, 14694, 14716, 14743, 14767, 14783,
|
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.
|
* Support for STT_GNU_IFUNC symbols added for s390 and s390x.
|
||||||
Optimized versions of memcpy, memset, and memcmp added for System z10 and
|
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, plus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||||
TEST_fff_f (fma, -min_value, -min_value, minus_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
|
#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.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);
|
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, plus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||||
TEST_fff_f (fma, -min_value, -min_value, minus_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
|
#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);
|
||||||
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, plus_zero, plus_zero, UNDERFLOW_EXCEPTION);
|
||||||
TEST_fff_f (fma, -min_value, -min_value, minus_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
|
#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);
|
||||||
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.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, 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, -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
|
#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.c00008p-127, UNDERFLOW_EXCEPTION);
|
||||||
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);
|
||||||
|
@@ -55,16 +55,17 @@ __fma (double x, double y, double z)
|
|||||||
underflows to 0. */
|
underflows to 0. */
|
||||||
if (z == 0 && x != 0 && y != 0)
|
if (z == 0 && x != 0 && y != 0)
|
||||||
return x * y;
|
return x * y;
|
||||||
/* If x or y or z is Inf/NaN, or if fma will certainly overflow,
|
/* If x or y or z is Inf/NaN, or if x * y is zero, compute as
|
||||||
or if x * y is zero, compute as x * y + z. */
|
x * y + z. */
|
||||||
if (u.ieee.exponent == 0x7ff
|
if (u.ieee.exponent == 0x7ff
|
||||||
|| v.ieee.exponent == 0x7ff
|
|| v.ieee.exponent == 0x7ff
|
||||||
|| w.ieee.exponent == 0x7ff
|
|| w.ieee.exponent == 0x7ff
|
||||||
|| u.ieee.exponent + v.ieee.exponent
|
|
||||||
> 0x7ff + IEEE754_DOUBLE_BIAS
|
|
||||||
|| x == 0
|
|| x == 0
|
||||||
|| y == 0)
|
|| y == 0)
|
||||||
return x * y + z;
|
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
|
/* If x * y is less than 1/4 of DBL_DENORM_MIN, neither the
|
||||||
result nor whether there is underflow depends on its exact
|
result nor whether there is underflow depends on its exact
|
||||||
value, only on its sign. */
|
value, only on its sign. */
|
||||||
|
@@ -56,16 +56,18 @@ __fmal (long double x, long double y, long double z)
|
|||||||
underflows to 0. */
|
underflows to 0. */
|
||||||
if (z == 0 && x != 0 && y != 0)
|
if (z == 0 && x != 0 && y != 0)
|
||||||
return x * y;
|
return x * y;
|
||||||
/* If x or y or z is Inf/NaN, or if fma will certainly overflow,
|
/* If x or y or z is Inf/NaN, or if x * y is zero, compute as
|
||||||
or if x * y is zero, compute as x * y + z. */
|
x * y + z. */
|
||||||
if (u.ieee.exponent == 0x7fff
|
if (u.ieee.exponent == 0x7fff
|
||||||
|| v.ieee.exponent == 0x7fff
|
|| v.ieee.exponent == 0x7fff
|
||||||
|| w.ieee.exponent == 0x7fff
|
|| w.ieee.exponent == 0x7fff
|
||||||
|| u.ieee.exponent + v.ieee.exponent
|
|
||||||
> 0x7fff + IEEE854_LONG_DOUBLE_BIAS
|
|
||||||
|| x == 0
|
|| x == 0
|
||||||
|| y == 0)
|
|| y == 0)
|
||||||
return x * y + z;
|
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
|
/* If x * y is less than 1/4 of LDBL_DENORM_MIN, neither the
|
||||||
result nor whether there is underflow depends on its exact
|
result nor whether there is underflow depends on its exact
|
||||||
value, only on its sign. */
|
value, only on its sign. */
|
||||||
|
@@ -56,16 +56,18 @@ __fmal (long double x, long double y, long double z)
|
|||||||
underflows to 0. */
|
underflows to 0. */
|
||||||
if (z == 0 && x != 0 && y != 0)
|
if (z == 0 && x != 0 && y != 0)
|
||||||
return x * y;
|
return x * y;
|
||||||
/* If x or y or z is Inf/NaN, or if fma will certainly overflow,
|
/* If x or y or z is Inf/NaN, or if x * y is zero, compute as
|
||||||
or if x * y is zero, compute as x * y + z. */
|
x * y + z. */
|
||||||
if (u.ieee.exponent == 0x7fff
|
if (u.ieee.exponent == 0x7fff
|
||||||
|| v.ieee.exponent == 0x7fff
|
|| v.ieee.exponent == 0x7fff
|
||||||
|| w.ieee.exponent == 0x7fff
|
|| w.ieee.exponent == 0x7fff
|
||||||
|| u.ieee.exponent + v.ieee.exponent
|
|
||||||
> 0x7fff + IEEE854_LONG_DOUBLE_BIAS
|
|
||||||
|| x == 0
|
|| x == 0
|
||||||
|| y == 0)
|
|| y == 0)
|
||||||
return x * y + z;
|
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
|
/* If x * y is less than 1/4 of LDBL_DENORM_MIN, neither the
|
||||||
result nor whether there is underflow depends on its exact
|
result nor whether there is underflow depends on its exact
|
||||||
value, only on its sign. */
|
value, only on its sign. */
|
||||||
|
Reference in New Issue
Block a user