diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | math/libm-test.inc | 52 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/e_hypot.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/flt-32/e_hypotf.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128/e_hypotl.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/e_hypotl.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/e_hypotl.c | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/e_hypot.c | 10 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/e_hypotf.c | 10 |
9 files changed, 91 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog index ab723ebfbb..039bba6657 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2016-12-07 Joseph Myers <joseph@codesourcery.com> + + [BZ #20940] + * sysdeps/ieee754/dbl-64/e_hypot.c (__ieee754_hypot): Do not + return Inf for arguments Inf and sNaN. + * sysdeps/ieee754/flt-32/e_hypotf.c (__ieee754_hypotf): Likewise. + * sysdeps/ieee754/ldbl-128/e_hypotl.c (__ieee754_hypotl): + Likewise. + * sysdeps/ieee754/ldbl-128ibm/e_hypotl.c (__ieee754_hypotl): + Likewise. + * sysdeps/ieee754/ldbl-96/e_hypotl.c (__ieee754_hypotl): Likewise. + * sysdeps/powerpc/fpu/e_hypot.c (TEST_INF_NAN): Do not return Inf + for arguments Inf and sNaN. When returning a NaN, compute it by + arithmetic on the arguments. + * sysdeps/powerpc/fpu/e_hypotf.c (TEST_INF_NAN): Likewise. + * math/libm-test.inc (pow_test_data): Add tests of sNaN arguments. + 2016-12-06 Joseph Myers <joseph@codesourcery.com> [BZ #20916] diff --git a/math/libm-test.inc b/math/libm-test.inc index 9123dcfc48..e973a3f6ae 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -8344,6 +8344,14 @@ static const struct test_ff_f_data hypot_test_data[] = TEST_ff_f (hypot, -qnan_value, plus_infty, plus_infty, ERRNO_UNCHANGED|NO_TEST_INLINE), TEST_ff_f (hypot, qnan_value, minus_infty, plus_infty, ERRNO_UNCHANGED|NO_TEST_INLINE), TEST_ff_f (hypot, -qnan_value, minus_infty, plus_infty, ERRNO_UNCHANGED|NO_TEST_INLINE), + TEST_ff_f (hypot, plus_infty, snan_value, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, plus_infty, -snan_value, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, minus_infty, snan_value, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, minus_infty, -snan_value, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, snan_value, plus_infty, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, -snan_value, plus_infty, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, snan_value, minus_infty, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), + TEST_ff_f (hypot, -snan_value, minus_infty, qnan_value, INVALID_EXCEPTION|NO_TEST_INLINE), TEST_ff_f (hypot, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, 0, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), @@ -8361,6 +8369,22 @@ static const struct test_ff_f_data hypot_test_data[] = TEST_ff_f (hypot, min_subnorm_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, -min_subnorm_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, -min_subnorm_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (hypot, 0, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, 0, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, minus_zero, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, minus_zero, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, max_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, max_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -max_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -max_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, min_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, min_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -min_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -min_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, min_subnorm_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, min_subnorm_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -min_subnorm_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -min_subnorm_value, -snan_value, qnan_value, INVALID_EXCEPTION), TEST_ff_f (hypot, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, -qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, qnan_value, minus_zero, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), @@ -8377,11 +8401,39 @@ static const struct test_ff_f_data hypot_test_data[] = TEST_ff_f (hypot, -qnan_value, min_subnorm_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, qnan_value, -min_subnorm_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, -qnan_value, -min_subnorm_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (hypot, snan_value, 0, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, 0, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, minus_zero, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, minus_zero, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, max_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, max_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, -max_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, -max_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, min_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, min_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, -min_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, -min_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, min_subnorm_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, min_subnorm_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, -min_subnorm_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, -min_subnorm_value, qnan_value, INVALID_EXCEPTION), TEST_ff_f (hypot, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, qnan_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, -qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (hypot, -qnan_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (hypot, qnan_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, qnan_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -qnan_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -qnan_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, qnan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, -qnan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, qnan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, -qnan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, snan_value, -snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, snan_value, qnan_value, INVALID_EXCEPTION), + TEST_ff_f (hypot, -snan_value, -snan_value, qnan_value, INVALID_EXCEPTION), AUTO_TESTS_ff_f (hypot), }; diff --git a/sysdeps/ieee754/dbl-64/e_hypot.c b/sysdeps/ieee754/dbl-64/e_hypot.c index f142c450a2..76eb408348 100644 --- a/sysdeps/ieee754/dbl-64/e_hypot.c +++ b/sysdeps/ieee754/dbl-64/e_hypot.c @@ -76,6 +76,8 @@ __ieee754_hypot (double x, double y) { u_int32_t low; w = a + b; /* for sNaN */ + if (issignaling (a) || issignaling (b)) + return w; GET_LOW_WORD (low, a); if (((ha & 0xfffff) | low) == 0) w = a; diff --git a/sysdeps/ieee754/flt-32/e_hypotf.c b/sysdeps/ieee754/flt-32/e_hypotf.c index 717b82e42f..fda2651a84 100644 --- a/sysdeps/ieee754/flt-32/e_hypotf.c +++ b/sysdeps/ieee754/flt-32/e_hypotf.c @@ -26,9 +26,9 @@ __ieee754_hypotf(float x, float y) ha &= 0x7fffffff; GET_FLOAT_WORD(hb,y); hb &= 0x7fffffff; - if (ha == 0x7f800000) + if (ha == 0x7f800000 && !issignaling (y)) return fabsf(x); - else if (hb == 0x7f800000) + else if (hb == 0x7f800000 && !issignaling (x)) return fabsf(y); else if (ha > 0x7f800000 || hb > 0x7f800000) return fabsf(x) * fabsf(y); diff --git a/sysdeps/ieee754/ldbl-128/e_hypotl.c b/sysdeps/ieee754/ldbl-128/e_hypotl.c index a93f5a4c8f..6c4e178fbe 100644 --- a/sysdeps/ieee754/ldbl-128/e_hypotl.c +++ b/sysdeps/ieee754/ldbl-128/e_hypotl.c @@ -67,6 +67,8 @@ __ieee754_hypotl(_Float128 x, _Float128 y) if(ha >= 0x7fff000000000000LL) { /* Inf or NaN */ u_int64_t low; w = a+b; /* for sNaN */ + if (issignaling (a) || issignaling (b)) + return w; GET_LDOUBLE_LSW64(low,a); if(((ha&0xffffffffffffLL)|low)==0) w = a; GET_LDOUBLE_LSW64(low,b); diff --git a/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c b/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c index c68dac03b0..de5a66ab05 100644 --- a/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c +++ b/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c @@ -67,6 +67,8 @@ __ieee754_hypotl(long double x, long double y) if(ha > 0x5f30000000000000LL) { /* a>2**500 */ if(ha >= 0x7ff0000000000000LL) { /* Inf or NaN */ w = a+b; /* for sNaN */ + if (issignaling (a) || issignaling (b)) + return w; if(ha == 0x7ff0000000000000LL) w = a; if(hb == 0x7ff0000000000000LL) diff --git a/sysdeps/ieee754/ldbl-96/e_hypotl.c b/sysdeps/ieee754/ldbl-96/e_hypotl.c index ee3a07055b..6b55b6d8ee 100644 --- a/sysdeps/ieee754/ldbl-96/e_hypotl.c +++ b/sysdeps/ieee754/ldbl-96/e_hypotl.c @@ -68,6 +68,8 @@ long double __ieee754_hypotl(long double x, long double y) u_int32_t exp __attribute__ ((unused)); u_int32_t high,low; w = a+b; /* for sNaN */ + if (issignaling (a) || issignaling (b)) + return w; GET_LDOUBLE_WORDS(exp,high,low,a); if(((high&0x7fffffff)|low)==0) w = a; GET_LDOUBLE_WORDS(exp,high,low,b); diff --git a/sysdeps/powerpc/fpu/e_hypot.c b/sysdeps/powerpc/fpu/e_hypot.c index da0f2daed3..65314c6ff5 100644 --- a/sysdeps/powerpc/fpu/e_hypot.c +++ b/sysdeps/powerpc/fpu/e_hypot.c @@ -41,10 +41,11 @@ static const double pdnum = 2.225073858507201e-308; #ifdef _ARCH_PWR7 /* POWER7 isinf and isnan optimization are fast. */ # define TEST_INF_NAN(x, y) \ - if (isinf(x) || isinf(y)) \ + if ((isinf(x) || isinf(y)) \ + && !issignaling (x) && !issignaling (y)) \ return INFINITY; \ if (isnan(x) || isnan(y)) \ - return NAN; + return x + y; # else /* For POWER6 and below isinf/isnan triggers LHS and PLT calls are * costly (especially for POWER6). */ @@ -66,9 +67,10 @@ static const double pdnum = 2.225073858507201e-308; uint32_t ht = hx; hx = hy; hy = ht; \ } \ if (hx >= 0x7ff00000) { \ - if (hx == 0x7ff00000 || hy == 0x7ff00000) \ + if ((hx == 0x7ff00000 || hy == 0x7ff00000) \ + && !issignaling (x) && !issignaling (y)) \ return INFINITY; \ - return NAN; \ + return x + y; \ } \ } while (0) diff --git a/sysdeps/powerpc/fpu/e_hypotf.c b/sysdeps/powerpc/fpu/e_hypotf.c index 48360828c3..c18281503c 100644 --- a/sysdeps/powerpc/fpu/e_hypotf.c +++ b/sysdeps/powerpc/fpu/e_hypotf.c @@ -31,10 +31,11 @@ #ifdef _ARCH_PWR7 /* POWER7 isinf and isnan optimizations are fast. */ # define TEST_INF_NAN(x, y) \ - if (isinff(x) || isinff(y)) \ + if ((isinff(x) || isinff(y)) \ + && !issignaling (x) && !issignaling (y)) \ return INFINITY; \ if (isnanf(x) || isnanf(y)) \ - return NAN; + return x + y; # else /* For POWER6 and below isinf/isnan triggers LHS and PLT calls are * costly (especially for POWER6). */ @@ -56,9 +57,10 @@ uint32_t ht = hx; hx = hy; hy = ht; \ } \ if (hx >= 0x7f800000) { \ - if (hx == 0x7f800000 || hy == 0x7f800000) \ + if ((hx == 0x7f800000 || hy == 0x7f800000) \ + && !issignaling (x) && !issignaling (y)) \ return INFINITY; \ - return NAN; \ + return x + y; \ } \ } while (0) #endif |