Fix missing overflow exceptions from pow (bug 13873).

This commit is contained in:
Joseph Myers 2012-04-09 09:43:18 +00:00
parent c483f6b4a4
commit d7dd945398
4 changed files with 19 additions and 15 deletions

View File

@ -1,5 +1,13 @@
2012-04-09 Joseph Myers <joseph@codesourcery.com>
[BZ #13873]
* sysdeps/ieee754/dbl-64/e_pow.c (huge, tiny): New variables.
(__ieee754_pow): Generate overflow and underflow using huge*huge
and tiny*tiny rather than just returning constant infinity or zero
for large exponents.
* math/libm-test.inc (pow_test): Require overflow exceptions for
applicable cases of large exponents.
[BZ #706]
* sysdeps/i386/fpu/e_pow.S (p10): New object.
(__ieee754_pow): Use iterative multiplication algorithm only for

6
NEWS
View File

@ -18,9 +18,9 @@ Version 2.16
13533, 13547, 13551, 13552, 13553, 13555, 13559, 13566, 13583, 13592,
13618, 13637, 13656, 13658, 13673, 13691, 13695, 13704, 13705, 13706,
13726, 13738, 13760, 13761, 13786, 13792, 13806, 13824, 13840, 13841,
13844, 13846, 13851, 13852, 13854, 13871, 13879, 13883, 13892, 13895,
13908, 13910, 13911, 13912, 13913, 13915, 13916, 13917, 13918, 13919,
13920, 13921, 13926, 13928, 13938
13844, 13846, 13851, 13852, 13854, 13871, 13873, 13879, 13883, 13892,
13895, 13908, 13910, 13911, 13912, 13913, 13915, 13916, 13917, 13918,
13919, 13920, 13921, 13926, 13928, 13938
* ISO C11 support:

View File

@ -5621,8 +5621,7 @@ pow_test (void)
TEST_ff_f (pow, 0x1p72L, 0x1p72L, plus_infty, OVERFLOW_EXCEPTION);
TEST_ff_f (pow, 10, -0x1p72L, 0);
/* Bug 13873: OVERFLOW exception may be missing. */
TEST_ff_f (pow, max_value, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
TEST_ff_f (pow, max_value, max_value, plus_infty, OVERFLOW_EXCEPTION);
/* Bug 13872: spurious OVERFLOW exception may be present. */
TEST_ff_f (pow, 10, -max_value, 0, OVERFLOW_EXCEPTION_OK);
@ -5908,8 +5907,7 @@ pow_test (void)
TEST_ff_f (pow, -2.0, 0x1.ffffffffffffffffffffffffffffp+113L, plus_infty, OVERFLOW_EXCEPTION);
# endif
#endif
/* Bug 13873: OVERFLOW exception may be missing. */
TEST_ff_f (pow, -2.0, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
TEST_ff_f (pow, -2.0, max_value, plus_infty, OVERFLOW_EXCEPTION);
TEST_ff_f (pow, -max_value, 0.5, nan_value, INVALID_EXCEPTION);
TEST_ff_f (pow, -max_value, 1.5, nan_value, INVALID_EXCEPTION);
@ -5962,8 +5960,7 @@ pow_test (void)
TEST_ff_f (pow, -max_value, 0x1.ffffffffffffffffffffffffffffp+113L, plus_infty, OVERFLOW_EXCEPTION);
# endif
#endif
/* Bug 13873: OVERFLOW exception may be missing. */
TEST_ff_f (pow, -max_value, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
TEST_ff_f (pow, -max_value, max_value, plus_infty, OVERFLOW_EXCEPTION);
TEST_ff_f (pow, -0.5, 126, 0x1p-126);
TEST_ff_f (pow, -0.5, 127, -0x1p-127);
@ -5990,8 +5987,7 @@ pow_test (void)
TEST_ff_f (pow, -0.5, -0x1.ffffffffffffffffffffffffffffp+113L, plus_infty, OVERFLOW_EXCEPTION);
# endif
#endif
/* Bug 13873: OVERFLOW exception may be missing. */
TEST_ff_f (pow, -0.5, -max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
TEST_ff_f (pow, -0.5, -max_value, plus_infty, OVERFLOW_EXCEPTION);
TEST_ff_f (pow, -0.5, 0xffffff, minus_zero);
TEST_ff_f (pow, -0.5, 0x1fffffe, plus_zero);
@ -6044,8 +6040,7 @@ pow_test (void)
TEST_ff_f (pow, -min_value, -0x1.ffffffffffffffffffffffffffffp+113L, plus_infty, OVERFLOW_EXCEPTION);
# endif
#endif
/* Bug 13873: OVERFLOW exception may be missing. */
TEST_ff_f (pow, -min_value, -max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
TEST_ff_f (pow, -min_value, -max_value, plus_infty, OVERFLOW_EXCEPTION);
TEST_ff_f (pow, -min_value, 0xffffff, minus_zero);
TEST_ff_f (pow, -min_value, 0x1fffffe, plus_zero);

View File

@ -47,6 +47,7 @@
# define SECTION
#endif
static const double huge = 1.0e300, tiny = 1.0e-300;
double __exp1(double x, double xx, double error);
static double log1(double x, double *delta, double *error);
@ -156,8 +157,8 @@ __ieee754_pow(double x, double y) {
if (qy > 0x45f00000 && qy < 0x7ff00000) {
if (x == 1.0) return 1.0;
if (y>0) return (x>1.0)?INF.x:0;
if (y<0) return (x<1.0)?INF.x:0;
if (y>0) return (x>1.0)?huge*huge:tiny*tiny;
if (y<0) return (x<1.0)?huge*huge:tiny*tiny;
}
if (x == 1.0) return 1.0;