From: Joseph Myers Date: Mon, 13 Jun 2016 17:27:19 +0000 (+0000) Subject: Fix frexp (NaN) (bug 20250). X-Git-Tag: glibc-2.24~108 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=88283451b26de29d08ba33148cf2f8cb2680f6f0;p=thirdparty%2Fglibc.git Fix frexp (NaN) (bug 20250). Various implementations of frexp functions return sNaN for sNaN input. This patch fixes them to add such arguments to themselves so that qNaN is returned. Tested for x86_64, x86, mips64 and powerpc. [BZ #20250] * sysdeps/i386/fpu/s_frexpl.S (__frexpl): Add non-finite input to itself. * sysdeps/ieee754/dbl-64/s_frexp.c (__frexp): Add non-finite or zero input to itself. * sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c (__frexp): Likewise. * sysdeps/ieee754/flt-32/s_frexpf.c (__frexpf): Likewise. * sysdeps/ieee754/ldbl-128/s_frexpl.c (__frexpl): Likewise. * sysdeps/ieee754/ldbl-128ibm/s_frexpl.c (__frexpl): Likewise. * sysdeps/ieee754/ldbl-96/s_frexpl.c (__frexpl): Likewise. * math/libm-test.inc (frexp_test_data): Add sNaN tests. --- diff --git a/ChangeLog b/ChangeLog index 84e6720fa40..49fc9e7800b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2016-06-13 Joseph Myers + + [BZ #20250] + * sysdeps/i386/fpu/s_frexpl.S (__frexpl): Add non-finite input to + itself. + * sysdeps/ieee754/dbl-64/s_frexp.c (__frexp): Add non-finite or + zero input to itself. + * sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c (__frexp): + Likewise. + * sysdeps/ieee754/flt-32/s_frexpf.c (__frexpf): Likewise. + * sysdeps/ieee754/ldbl-128/s_frexpl.c (__frexpl): Likewise. + * sysdeps/ieee754/ldbl-128ibm/s_frexpl.c (__frexpl): Likewise. + * sysdeps/ieee754/ldbl-96/s_frexpl.c (__frexpl): Likewise. + * math/libm-test.inc (frexp_test_data): Add sNaN tests. + 2016-06-13 Adhemerval Zanella * nptl/Makefile (test): Add tst-cancel4_1 and tst-cancel4_2. diff --git a/math/libm-test.inc b/math/libm-test.inc index 3d901ae96a5..81ca8966266 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -7760,6 +7760,8 @@ static const struct test_f_f1_data frexp_test_data[] = TEST_fI_f1 (frexp, minus_infty, minus_infty, IGNORE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_fI_f1 (frexp, qnan_value, qnan_value, IGNORE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_fI_f1 (frexp, -qnan_value, qnan_value, IGNORE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fI_f1 (frexp, snan_value, qnan_value, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_fI_f1 (frexp, -snan_value, qnan_value, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_fI_f1 (frexp, 0.0, 0.0, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_fI_f1 (frexp, minus_zero, minus_zero, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), diff --git a/sysdeps/i386/fpu/s_frexpl.S b/sysdeps/i386/fpu/s_frexpl.S index f687ab3c2ed..b33a8a85738 100644 --- a/sysdeps/i386/fpu/s_frexpl.S +++ b/sysdeps/i386/fpu/s_frexpl.S @@ -50,7 +50,7 @@ ENTRY (__frexpl) jz 1f xorl %ecx, %ecx cmpl $0x7fff, %eax - je 1f + je 3f cmpl $0, %eax jne 2f @@ -81,5 +81,12 @@ ENTRY (__frexpl) movl %ecx, (%eax) ret + + /* Infinity or NaN; ensure signaling NaNs are quieted. */ +3: movl EXPP(%esp), %eax + fldt VAL0(%esp) + fadd %st + movl %ecx, (%eax) + ret END (__frexpl) weak_alias (__frexpl, frexpl) diff --git a/sysdeps/ieee754/dbl-64/s_frexp.c b/sysdeps/ieee754/dbl-64/s_frexp.c index 1b8d8500ba8..874214ec7c8 100644 --- a/sysdeps/ieee754/dbl-64/s_frexp.c +++ b/sysdeps/ieee754/dbl-64/s_frexp.c @@ -38,7 +38,7 @@ __frexp (double x, int *eptr) ix = 0x7fffffff & hx; *eptr = 0; if (ix >= 0x7ff00000 || ((ix | lx) == 0)) - return x; /* 0,inf,nan */ + return x + x; /* 0,inf,nan */ if (ix < 0x00100000) /* subnormal */ { x *= two54; diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c index 42068f8187f..4b075b72005 100644 --- a/sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c @@ -55,6 +55,9 @@ __frexp (double x, int *eptr) ix = (ix & INT64_C (0x800fffffffffffff)) | INT64_C (0x3fe0000000000000); INSERT_WORDS64 (x, ix); } + else + /* Quiet signaling NaNs. */ + x += x; *eptr = e; return x; diff --git a/sysdeps/ieee754/flt-32/s_frexpf.c b/sysdeps/ieee754/flt-32/s_frexpf.c index 67a28d36036..005367cf585 100644 --- a/sysdeps/ieee754/flt-32/s_frexpf.c +++ b/sysdeps/ieee754/flt-32/s_frexpf.c @@ -29,7 +29,7 @@ float __frexpf(float x, int *eptr) GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; *eptr = 0; - if(ix>=0x7f800000||(ix==0)) return x; /* 0,inf,nan */ + if(ix>=0x7f800000||(ix==0)) return x + x; /* 0,inf,nan */ if (ix<0x00800000) { /* subnormal */ x *= two25; GET_FLOAT_WORD(hx,x); diff --git a/sysdeps/ieee754/ldbl-128/s_frexpl.c b/sysdeps/ieee754/ldbl-128/s_frexpl.c index d61dddaaaa7..70b2d3ae190 100644 --- a/sysdeps/ieee754/ldbl-128/s_frexpl.c +++ b/sysdeps/ieee754/ldbl-128/s_frexpl.c @@ -39,7 +39,7 @@ long double __frexpl(long double x, int *eptr) GET_LDOUBLE_WORDS64(hx,lx,x); ix = 0x7fffffffffffffffULL&hx; *eptr = 0; - if(ix>=0x7fff000000000000ULL||((ix|lx)==0)) return x; /* 0,inf,nan */ + if(ix>=0x7fff000000000000ULL||((ix|lx)==0)) return x + x;/* 0,inf,nan */ if (ix<0x0001000000000000ULL) { /* subnormal */ x *= two114; GET_LDOUBLE_MSW64(hx,x); diff --git a/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c b/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c index 52d2d3ea900..210c5d2ed4f 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c @@ -47,7 +47,7 @@ long double __frexpl(long double x, int *eptr) { /* 0,inf,nan. */ *eptr = expon; - return x; + return x + x; } expon = ix >> 52; if (expon == 0) diff --git a/sysdeps/ieee754/ldbl-96/s_frexpl.c b/sysdeps/ieee754/ldbl-96/s_frexpl.c index ab217a659b6..799880f3738 100644 --- a/sysdeps/ieee754/ldbl-96/s_frexpl.c +++ b/sysdeps/ieee754/ldbl-96/s_frexpl.c @@ -46,7 +46,7 @@ long double __frexpl(long double x, int *eptr) GET_LDOUBLE_WORDS(se,hx,lx,x); ix = 0x7fff&se; *eptr = 0; - if(ix==0x7fff||((ix|hx|lx)==0)) return x; /* 0,inf,nan */ + if(ix==0x7fff||((ix|hx|lx)==0)) return x + x; /* 0,inf,nan */ if (ix==0x0000) { /* subnormal */ x *= two65; GET_LDOUBLE_EXP(se,x);