aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
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 /sysdeps
parentb39b6e0c902f0bf5f99d593b8f5953943777c610 (diff)
downloadglibc-88283451b26de29d08ba33148cf2f8cb2680f6f0.zip
glibc-88283451b26de29d08ba33148cf2f8cb2680f6f0.tar.gz
glibc-88283451b26de29d08ba33148cf2f8cb2680f6f0.tar.bz2
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.
Diffstat (limited to 'sysdeps')
-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
7 files changed, 16 insertions, 6 deletions
diff --git a/sysdeps/i386/fpu/s_frexpl.S b/sysdeps/i386/fpu/s_frexpl.S
index f687ab3..b33a8a8 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 1b8d850..874214e 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 42068f8..4b075b7 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 67a28d3..005367c 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 d61ddda..70b2d3a 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 52d2d3e..210c5d2 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 ab217a6..799880f 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);