This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix j1, jn missing underflows (bug 16559) [committed]


Similar to various other bugs in this area, j1 and jn implementations
can fail to raise the underflow exception when the internal
computation is exact although the actual function is inexact.  This
patch forces the exception in a similar way to other such fixes.  (The
ldbl-128 / ldbl-128ibm j1l implementation is different and doesn't
need a change for this until spurious underflows in it are fixed.)

Tested for x86_64, x86, mips64 and powerpc.  Committed.

(auto-libm-test-out diffs omitted below.)

2015-06-29  Joseph Myers  <joseph@codesourcery.com>

	[BZ #16559]
	* sysdeps/ieee754/dbl-64/e_j1.c: Include <float.h>.
	(__ieee754_j1): Force underflow exception for small results.
	* sysdeps/ieee754/dbl-64/e_jn.c (__ieee754_jn): Likewise.
	* sysdeps/ieee754/flt-32/e_j1f.c: Include <float.h>.
	(__ieee754_j1f): Force underflow exception for small results.
	* sysdeps/ieee754/flt-32/e_jnf.c (__ieee754_jnf): Likewise.
	* sysdeps/ieee754/ldbl-128/e_jnl.c (__ieee754_jnl): Likewise.
	* sysdeps/ieee754/ldbl-128ibm/e_jnl.c (__ieee754_jnl): Likewise.
	* sysdeps/ieee754/ldbl-96/e_j1l.c: Include <float.h>.
	(__ieee754_j1l): Force underflow exception for small results.
	* sysdeps/ieee754/ldbl-96/e_jnl.c (__ieee754_jnl): Likewise.
	* math/auto-libm-test-in: Add more tests of j1 and jn.
	* math/auto-libm-test-out: Regenerated.

diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index 75cf545..34b02c9 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -1812,6 +1812,11 @@ j1 0x1.ff00000000002p+840
 j1 0x1p1023
 j1 0x1p16382
 j1 0x1p16383
+# Bug 18611: errno setting may be missing.
+j1 min missing-errno
+j1 -min missing-errno
+j1 min_subnorm missing-errno
+j1 -min_subnorm missing-errno
 
 # jn (0, x) == j0 (x).
 jn 0 -1.0
@@ -1836,6 +1841,11 @@ jn 1 1.5
 jn 1 2.0
 jn 1 8.0
 jn 1 10.0
+# Bug 18611: errno setting may be missing.
+jn 1 min missing-errno
+jn 1 -min missing-errno
+jn 1 min_subnorm missing-errno
+jn 1 -min_subnorm missing-errno
 
 jn 3 -1.0
 jn 3 0.0
@@ -1867,6 +1877,12 @@ jn 2 0x1p127
 jn 2 0x1p1023
 jn 2 0x1p16383
 
+# Bug 18611: errno setting may be missing.
+jn 10 min missing-errno
+jn 10 -min missing-errno
+jn 10 min_subnorm missing-errno
+jn 10 -min_subnorm missing-errno
+
 lgamma max
 lgamma 1
 lgamma 3
diff --git a/sysdeps/ieee754/dbl-64/e_j1.c b/sysdeps/ieee754/dbl-64/e_j1.c
index 653f33a..26ffdfe 100644
--- a/sysdeps/ieee754/dbl-64/e_j1.c
+++ b/sysdeps/ieee754/dbl-64/e_j1.c
@@ -59,6 +59,7 @@
  */
 
 #include <errno.h>
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -124,8 +125,16 @@ __ieee754_j1 (double x)
     }
   if (__glibc_unlikely (ix < 0x3e400000))                  /* |x|<2**-27 */
     {
-      if (huge + x > one)
-	return 0.5 * x;                 /* inexact if x!=0 necessary */
+      if (huge + x > one)                 /* inexact if x!=0 necessary */
+	{
+	  double ret = 0.5 * x;
+	  if (fabs (ret) < DBL_MIN)
+	    {
+	      double force_underflow = ret * ret;
+	      math_force_eval (force_underflow);
+	    }
+	  return ret;
+	}
     }
   z = x * x;
   r1 = z * R[0]; z2 = z * z;
diff --git a/sysdeps/ieee754/dbl-64/e_jn.c b/sysdeps/ieee754/dbl-64/e_jn.c
index b0ddd5e..ccef2dc 100644
--- a/sysdeps/ieee754/dbl-64/e_jn.c
+++ b/sysdeps/ieee754/dbl-64/e_jn.c
@@ -246,6 +246,11 @@ __ieee754_jn (int n, double x)
   }
   if (ret == 0)
     ret = __copysign (DBL_MIN, ret) * DBL_MIN;
+  else if (fabs (ret) < DBL_MIN)
+    {
+      double force_underflow = ret * ret;
+      math_force_eval (force_underflow);
+    }
   return ret;
 }
 strong_alias (__ieee754_jn, __jn_finite)
diff --git a/sysdeps/ieee754/flt-32/e_j1f.c b/sysdeps/ieee754/flt-32/e_j1f.c
index 7ffb57e..63de21f 100644
--- a/sysdeps/ieee754/flt-32/e_j1f.c
+++ b/sysdeps/ieee754/flt-32/e_j1f.c
@@ -14,6 +14,7 @@
  */
 
 #include <errno.h>
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -69,7 +70,14 @@ __ieee754_j1f(float x)
 		else	 return  z;
 	}
 	if(__builtin_expect(ix<0x32000000, 0)) {	/* |x|<2**-27 */
-	    if(huge+x>one) return (float)0.5*x;/* inexact if x!=0 necessary */
+	    if(huge+x>one) {		/* inexact if x!=0 necessary */
+		float ret = (float) 0.5 * x;
+		if (fabsf (ret) < FLT_MIN) {
+		    float force_underflow = ret * ret;
+		    math_force_eval (force_underflow);
+		}
+		return ret;
+	    }
 	}
 	z = x*x;
 	r =  z*(r00+z*(r01+z*(r02+z*r03)));
diff --git a/sysdeps/ieee754/flt-32/e_jnf.c b/sysdeps/ieee754/flt-32/e_jnf.c
index ec5a81b..44a3761 100644
--- a/sysdeps/ieee754/flt-32/e_jnf.c
+++ b/sysdeps/ieee754/flt-32/e_jnf.c
@@ -170,6 +170,10 @@ __ieee754_jnf(int n, float x)
     }
     if (ret == 0)
 	ret = __copysignf (FLT_MIN, ret) * FLT_MIN;
+    else if (fabsf (ret) < FLT_MIN) {
+	float force_underflow = ret * ret;
+	math_force_eval (force_underflow);
+    }
     return ret;
 }
 strong_alias (__ieee754_jnf, __jnf_finite)
diff --git a/sysdeps/ieee754/ldbl-128/e_jnl.c b/sysdeps/ieee754/ldbl-128/e_jnl.c
index 14d65ff..a419994 100644
--- a/sysdeps/ieee754/ldbl-128/e_jnl.c
+++ b/sysdeps/ieee754/ldbl-128/e_jnl.c
@@ -297,6 +297,11 @@ __ieee754_jnl (int n, long double x)
   }
   if (ret == 0)
     ret = __copysignl (LDBL_MIN, ret) * LDBL_MIN;
+  else if (fabsl (ret) < LDBL_MIN)
+    {
+      long double force_underflow = ret * ret;
+      math_force_eval (force_underflow);
+    }
   return ret;
 }
 strong_alias (__ieee754_jnl, __jnl_finite)
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_jnl.c b/sysdeps/ieee754/ldbl-128ibm/e_jnl.c
index 5d0a2b5..7594196 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_jnl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_jnl.c
@@ -297,6 +297,11 @@ __ieee754_jnl (int n, long double x)
   }
   if (ret == 0)
     ret = __copysignl (LDBL_MIN, ret) * LDBL_MIN;
+  else if (fabsl (ret) < LDBL_MIN)
+    {
+      long double force_underflow = ret * ret;
+      math_force_eval (force_underflow);
+    }
   return ret;
 }
 strong_alias (__ieee754_jnl, __jnl_finite)
diff --git a/sysdeps/ieee754/ldbl-96/e_j1l.c b/sysdeps/ieee754/ldbl-96/e_j1l.c
index 1bd5499..46e28df 100644
--- a/sysdeps/ieee754/ldbl-96/e_j1l.c
+++ b/sysdeps/ieee754/ldbl-96/e_j1l.c
@@ -72,6 +72,7 @@
  */
 
 #include <errno.h>
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -150,8 +151,16 @@ __ieee754_j1l (long double x)
     }
   if (__glibc_unlikely (ix < 0x3fde))       /* |x| < 2^-33 */
     {
-      if (huge + x > one)
-	return 0.5 * x;		/* inexact if x!=0 necessary */
+      if (huge + x > one)		/* inexact if x!=0 necessary */
+	{
+	  long double ret = 0.5 * x;
+	  if (fabsl (ret) < LDBL_MIN)
+	    {
+	      long double force_underflow = ret * ret;
+	      math_force_eval (force_underflow);
+	    }
+	  return ret;
+	}
     }
   z = x * x;
   r = z * (R[0] + z * (R[1]+ z * (R[2] + z * (R[3] + z * R[4]))));
diff --git a/sysdeps/ieee754/ldbl-96/e_jnl.c b/sysdeps/ieee754/ldbl-96/e_jnl.c
index 49c9c42..2f3a452 100644
--- a/sysdeps/ieee754/ldbl-96/e_jnl.c
+++ b/sysdeps/ieee754/ldbl-96/e_jnl.c
@@ -290,6 +290,11 @@ __ieee754_jnl (int n, long double x)
   }
   if (ret == 0)
     ret = __copysignl (LDBL_MIN, ret) * LDBL_MIN;
+  else if (fabsl (ret) < LDBL_MIN)
+    {
+      long double force_underflow = ret * ret;
+      math_force_eval (force_underflow);
+    }
   return ret;
 }
 strong_alias (__ieee754_jnl, __jnl_finite)

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]