]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix spurious "inexact" exceptions from dbl-64 sqrt (bug 15631).
authorJoseph Myers <joseph@codesourcery.com>
Sat, 15 Jun 2013 19:59:41 +0000 (19:59 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Sat, 15 Jun 2013 19:59:41 +0000 (19:59 +0000)
ChangeLog
NEWS
sysdeps/ieee754/dbl-64/e_sqrt.c

index bf4e137669a70e0f186cd751c921230c7b113e69..af0d2433f0e7b3bbfebf0c5993c453ff810df5a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2013-06-15  Joseph Myers  <joseph@codesourcery.com>
 
+       [BZ #15631]
+       * sysdeps/ieee754/dbl-64/e_sqrt.c (__ieee754_sqrt): Save and
+       restore exception state around main square root computation, then
+       check for inexactness explicitly.
+
        * math/libm-test.inc (fma_test_data): Add another test.
 
 2013-06-15  Siddhesh Poyarekar  <siddhesh@redhat.com>
diff --git a/NEWS b/NEWS
index ea9c6a0dd2b1099c9006546bf1b3269ae9ee7d76..63f28927be2a234be49be62671201f115c8e70c0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,7 +20,7 @@ Version 2.18
   15366, 15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418,
   15419, 15423, 15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448,
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529,
-  15536, 15553, 15577, 15583, 15618, 15627.
+  15536, 15553, 15577, 15583, 15618, 15627, 15631.
 
 * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
   #15078).
index f90ea0c076a5191012e59625e9f5503c032a482c..54610eeeab20f7e1a403adfcac81410146497ad0 100644 (file)
@@ -63,6 +63,9 @@ double __ieee754_sqrt(double x) {
   s=a.x;
   /*----------------- 2^-1022  <= | x |< 2^1024  -----------------*/
   if (k>0x000fffff && k<0x7ff00000) {
+    fenv_t env;
+    libc_feholdexcept (&env);
+    double ret;
     y=1.0-t*(t*s);
     t=t*(rt0+y*(rt1+y*(rt2+y*rt3)));
     c.i[HIGH_HALF]=0x20000000+((k&0x7fe00000)>>1);
@@ -70,12 +73,22 @@ double __ieee754_sqrt(double x) {
     hy=(y+big)-big;
     del=0.5*t*((s-hy*hy)-(y-hy)*(y+hy));
     res=y+del;
-    if (res == (res+1.002*((y-res)+del))) return res*c.x;
+    if (res == (res+1.002*((y-res)+del))) ret = res*c.x;
     else {
       res1=res+1.5*((y-res)+del);
       EMULV(res,res1,z,zz,p,hx,tx,hy,ty);  /* (z+zz)=res*res1 */
-      return ((((z-s)+zz)<0)?max(res,res1):min(res,res1))*c.x;
+      ret = ((((z-s)+zz)<0)?max(res,res1):min(res,res1))*c.x;
     }
+    math_force_eval (ret);
+    libc_fesetenv (&env);
+    if (x / ret != ret)
+      {
+       double force_inexact = 1.0 / 3.0;
+       math_force_eval (force_inexact);
+      }
+    /* Otherwise (x / ret == ret), either the square root was exact or
+       the division was inexact.  */
+    return ret;
   }
   else {
     if ((k & 0x7ff00000) == 0x7ff00000)