1
0
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:
Joseph Myers
2012-11-04 19:26:02 +00:00
parent b830319d49
commit a0c2940d67
6 changed files with 66 additions and 13 deletions

View File

@@ -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
View File

@@ -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

View File

@@ -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);

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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. */