about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2016-06-13 17:27:19 +0000
committerJoseph Myers <joseph@codesourcery.com>2016-06-13 17:27:19 +0000
commit88283451b26de29d08ba33148cf2f8cb2680f6f0 (patch)
tree334945ab68b411d9bac8696fbcaba40a6598ed2b
parentb39b6e0c902f0bf5f99d593b8f5953943777c610 (diff)
downloadglibc-88283451b26de29d08ba33148cf2f8cb2680f6f0.tar.gz
glibc-88283451b26de29d08ba33148cf2f8cb2680f6f0.tar.xz
glibc-88283451b26de29d08ba33148cf2f8cb2680f6f0.zip
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.
-rw-r--r--ChangeLog15
-rw-r--r--math/libm-test.inc2
-rw-r--r--sysdeps/i386/fpu/s_frexpl.S9
-rw-r--r--sysdeps/ieee754/dbl-64/s_frexp.c2
-rw-r--r--sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c3
-rw-r--r--sysdeps/ieee754/flt-32/s_frexpf.c2
-rw-r--r--sysdeps/ieee754/ldbl-128/s_frexpl.c2
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_frexpl.c2
-rw-r--r--sysdeps/ieee754/ldbl-96/s_frexpl.c2
9 files changed, 33 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 84e6720fa4..49fc9e7800 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 3d901ae96a..81ca896626 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 f687ab3c2e..b33a8a8573 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 1b8d8500ba..874214ec7c 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 42068f8187..4b075b7200 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 67a28d3603..005367cf58 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 d61dddaaaa..70b2d3ae19 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 52d2d3ea90..210c5d2ed4 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 ab217a659b..799880f373 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);