]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix frexp (NaN) (bug 20250).
authorJoseph Myers <joseph@codesourcery.com>
Mon, 13 Jun 2016 17:27:19 +0000 (17:27 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Mon, 13 Jun 2016 17:27:19 +0000 (17:27 +0000)
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.

ChangeLog
math/libm-test.inc
sysdeps/i386/fpu/s_frexpl.S
sysdeps/ieee754/dbl-64/s_frexp.c
sysdeps/ieee754/dbl-64/wordsize-64/s_frexp.c
sysdeps/ieee754/flt-32/s_frexpf.c
sysdeps/ieee754/ldbl-128/s_frexpl.c
sysdeps/ieee754/ldbl-128ibm/s_frexpl.c
sysdeps/ieee754/ldbl-96/s_frexpl.c

index 84e6720fa40b1c845464fa2845d4051dbde02004..49fc9e7800b161e3814de0f774fbe89f9914ae5a 100644 (file)
--- 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.
index 3d901ae96a5ac3cf9099e9ae6d760b91eec3cd09..81ca89662668de737c8eb368b855aba93c72ff28 100644 (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),
index f687ab3c2edb03a22821e417b945790a31583cf7..b33a8a85738202a0fc3cd9477344e0639fdacf47 100644 (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)
index 1b8d8500ba89909319c05556ba79ce14593b1e28..874214ec7c8a746313afb72d2cc79a93b029fdb7 100644 (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;
index 42068f8187ffdfd6382308c33f37fcf7049c34f6..4b075b720052ddec1d1fa4b939bff1c463ddddbf 100644 (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;
index 67a28d3603693844a8c9fc9315c94af2c3b6d2d1..005367cf585d96733880fa83e856de7dc3b33851 100644 (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);
index d61dddaaaa73daef69435888afe3df173c16acc0..70b2d3ae190dc366e9f3d63bd114c89400aadf55 100644 (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);
index 52d2d3ea900c1922796cc49cf09d4525df5db3f1..210c5d2ed4fba9a8f25cfc7af927252dee323461 100644 (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)
index ab217a659b624278f36ba295575c106db517d7b5..799880f37389c7b0e4d24e2b5782f1561c7b810e 100644 (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);