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 tan missing underflows (bug 16517) [committed]


Similar to various other bugs in this area, some tan implementations
do not raise the underflow exception for subnormal arguments, when the
result is tiny and inexact.  This patch forces the exception in a
similar way to previous fixes.

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

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

2015-08-07  Joseph Myers  <joseph@codesourcery.com>

	[BZ #16517]
	* sysdeps/ieee754/dbl-64/s_tan.c: Include <float.h>.
	(tan): Force underflow exception for arguments with small absolute
	value.
	* sysdeps/ieee754/flt-32/k_tanf.c: Include <float.h>.
	(__kernel_tanf): Force underflow exception for arguments with
	small absolute value.
	* sysdeps/ieee754/ldbl-128/k_tanl.c: Include <float.h>.
	(__kernel_tanl): Force underflow exception for arguments with
	small absolute value.
	* sysdeps/ieee754/ldbl-128ibm/k_tanl.c: Include <float.h>.
	(__kernel_tanl): Force underflow exception for arguments with
	small absolute value.
	* sysdeps/ieee754/ldbl-96/k_tanl.c: Include <float.h>.
	(__kernel_tanl): Force underflow exception for arguments with
	small absolute value.
	* math/auto-libm-test-in: Add more tests of tan.
	* math/auto-libm-test-out: Regenerated.

diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index cc9b7fd..bb6d30e 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -2659,6 +2659,10 @@ tan 9
 tan 10
 tan -0x1.062a48p+0
 tan -0x1.4f69cp+0
+tan min
+tan -min
+tan min_subnorm
+tan -min_subnorm
 
 tanh 0
 tanh -0
diff --git a/sysdeps/ieee754/dbl-64/s_tan.c b/sysdeps/ieee754/dbl-64/s_tan.c
index dcb4aca..b4e3bd2 100644
--- a/sysdeps/ieee754/dbl-64/s_tan.c
+++ b/sysdeps/ieee754/dbl-64/s_tan.c
@@ -34,6 +34,7 @@
 /*********************************************************************/
 
 #include <errno.h>
+#include <float.h>
 #include "endian.h"
 #include <dla.h>
 #include "mpa.h"
@@ -91,6 +92,11 @@ tan (double x)
   /* (I) The case abs(x) <= 1.259e-8 */
   if (w <= g1.d)
     {
+      if (w < DBL_MIN)
+	{
+	  double force_underflow = x * x;
+	  math_force_eval (force_underflow);
+	}
       retval = x;
       goto ret;
     }
diff --git a/sysdeps/ieee754/flt-32/k_tanf.c b/sysdeps/ieee754/flt-32/k_tanf.c
index a67f36e..2f2076d 100644
--- a/sysdeps/ieee754/flt-32/k_tanf.c
+++ b/sysdeps/ieee754/flt-32/k_tanf.c
@@ -17,6 +17,7 @@
 static char rcsid[] = "$NetBSD: k_tanf.c,v 1.4 1995/05/10 20:46:39 jtc Exp $";
 #endif
 
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 static const float
@@ -48,7 +49,17 @@ float __kernel_tanf(float x, float y, int iy)
 	if(ix<0x39000000)			/* x < 2**-13 */
 	    {if((int)x==0) {			/* generate inexact */
 		if((ix|(iy+1))==0) return one/fabsf(x);
-		else return (iy==1)? x: -one/x;
+		else if (iy == 1)
+		  {
+		    if (fabsf (x) < FLT_MIN)
+		      {
+			float force_underflow = x * x;
+			math_force_eval (force_underflow);
+		      }
+		    return x;
+		  }
+		else
+		  return -one / x;
 	    }
 	    }
 	if(ix>=0x3f2ca140) { 			/* |x|>=0.6744 */
diff --git a/sysdeps/ieee754/ldbl-128/k_tanl.c b/sysdeps/ieee754/ldbl-128/k_tanl.c
index dfba2d9..6a6fa9f 100644
--- a/sysdeps/ieee754/ldbl-128/k_tanl.c
+++ b/sysdeps/ieee754/ldbl-128/k_tanl.c
@@ -56,6 +56,7 @@
  *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
  */
 
+#include <float.h>
 #include <libc-internal.h>
 #include <math.h>
 #include <math_private.h>
@@ -98,8 +99,17 @@ __kernel_tanl (long double x, long double y, int iy)
 	  if ((ix | u.parts32.w1 | u.parts32.w2 | u.parts32.w3
 	       | (iy + 1)) == 0)
 	    return one / fabs (x);
+	  else if (iy == 1)
+	    {
+	      if (fabsl (x) < LDBL_MIN)
+		{
+		  long double force_underflow = x * x;
+		  math_force_eval (force_underflow);
+		}
+	      return x;
+	    }
 	  else
-	    return (iy == 1) ? x : -one / x;
+	    return -one / x;
 	}
     }
   if (ix >= 0x3ffe5942) /* |x| >= 0.6743316650390625 */
diff --git a/sysdeps/ieee754/ldbl-128ibm/k_tanl.c b/sysdeps/ieee754/ldbl-128ibm/k_tanl.c
index 7f1caee..e50cc88 100644
--- a/sysdeps/ieee754/ldbl-128ibm/k_tanl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/k_tanl.c
@@ -56,6 +56,7 @@
  *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
  */
 
+#include <float.h>
 #include <libc-internal.h>
 #include <math.h>
 #include <math_private.h>
@@ -98,8 +99,17 @@ __kernel_tanl (long double x, long double y, int iy)
 	{
 	  if ((ix | lx | (iy + 1)) == 0)
 	    return one / fabs (x);
+	  else if (iy == 1)
+	    {
+	      if (fabsl (x) < LDBL_MIN)
+		{
+		  long double force_underflow = x * x;
+		  math_force_eval (force_underflow);
+		}
+	      return x;
+	    }
 	  else
-	    return (iy == 1) ? x : -one / x;
+	    return -one / x;
 	}
     }
   if (ix >= 0x3fe59420) /* |x| >= 0.6743316650390625 */
diff --git a/sysdeps/ieee754/ldbl-96/k_tanl.c b/sysdeps/ieee754/ldbl-96/k_tanl.c
index 31cd236..ae6821d 100644
--- a/sysdeps/ieee754/ldbl-96/k_tanl.c
+++ b/sysdeps/ieee754/ldbl-96/k_tanl.c
@@ -56,6 +56,7 @@
  *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
  */
 
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 static const long double
@@ -94,8 +95,17 @@ __kernel_tanl (long double x, long double y, int iy)
 	{			/* generate inexact */
 	  if (x == 0 && iy == -1)
 	    return one / fabsl (x);
+	  else if (iy == 1)
+	    {
+	      if (absx < LDBL_MIN)
+		{
+		  long double force_underflow = x * x;
+		  math_force_eval (force_underflow);
+		}
+	      return x;
+	    }
 	  else
-	    return (iy == 1) ? x : -one / x;
+	    return -one / x;
 	}
     }
   if (absx >= 0.6743316650390625L)

-- 
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]