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.
This commit is contained in:
Joseph Myers 2016-06-13 17:27:19 +00:00
parent b39b6e0c90
commit 88283451b2
9 changed files with 33 additions and 6 deletions

View File

@ -1,3 +1,18 @@
2016-06-13 Joseph Myers <joseph@codesourcery.com>
[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 <adhemerval.zanella@linaro.org>
* nptl/Makefile (test): Add tst-cancel4_1 and tst-cancel4_2.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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