changeset 8563:c3d334708928

Better support of signalling NaNs.
author Bruno Haible <bruno@clisp.org>
date Mon, 26 Mar 2007 22:26:05 +0000
parents 6fd01943c239
children 4da0aa038935
files ChangeLog lib/atanl.c lib/cosl.c lib/ldexpl.c lib/logl.c lib/sinl.c lib/sqrtl.c lib/tanl.c lib/trigl.c
diffstat 9 files changed, 70 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2007-03-26  Bruno Haible  <bruno@clisp.org>
+
+	Better support of signalling NaNs.
+	* lib/atanl.c: Include isnanl.h.
+	(atanl): Perform test for NaN at the beginning of the function and
+	through a call to isnanl.
+	* lib/cosl.c: Include isnanl.h.
+	(cosl): Perform test for NaN at the beginning of the function and
+	through a call to isnanl.
+	* lib/ldexpl.c: Include isnanl.h.
+	(ldexpl): Perform test for NaN through a call to isnanl.
+	* lib/logl.c: Include isnanl.h.
+	(logl): Perform test for NaN at the beginning of the function and
+	through a call to isnanl.
+	* lib/sinl.c: Include isnanl.h.
+	(sinl): Perform test for NaN at the beginning of the function and
+	through a call to isnanl.
+	* lib/sqrtl.c: Include isnanl.h.
+	(sqrtl): Perform test for NaN at the beginning of the function and
+	through a call to isnanl.
+	* lib/tanl.c: Include isnanl.h.
+	(tanl): Perform test for NaN at the beginning of the function and
+	through a call to isnanl.
+	* lib/trigl.c (ieee754_rem_pio2l): Remove test for NaN.
+
 2007-03-26  Eric Blake  <ebb9@byu.net>
 
 	* m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_DIRECTIVE_A): Fix
--- a/lib/atanl.c
+++ b/lib/atanl.c
@@ -64,6 +64,7 @@
  *
  */
 
+#include "isnanl.h"
 
 /* arctan(k/8), k = 0, ..., 82 */
 static const long double atantbl[84] = {
@@ -178,11 +179,11 @@
   int k, sign;
   long double t, u, p, q;
 
-  sign = x < 0.0;
+  /* Check for zero or NaN.  */
+  if (isnanl (x) || x == 0.0)
+    return x + x;
 
-  /* Check for zero or NaN.  */
-  if (x != x || x == 0.0)
-    return x + x;
+  sign = x < 0.0;
 
   if (x + x == x)
     {
--- a/lib/cosl.c
+++ b/lib/cosl.c
@@ -54,19 +54,24 @@
 #include "trigl.c"
 #include "sincosl.c"
 #endif
+#include "isnanl.h"
 
 long double cosl(long double x)
 {
 	long double y[2],z=0.0L;
 	int n;
 
+    /* cosl(NaN) is NaN */
+        if (isnanl (x))
+          return x;
+
     /* |x| ~< pi/4 */
         if(x >= -0.7853981633974483096156608458198757210492 &&
            x <= 0.7853981633974483096156608458198757210492)
           return kernel_cosl(x, z);
 
-    /* sinl(Inf or NaN) is NaN, sinl(0) is 0 */
-        else if ((x + x == x && x != 0.0) || x != x)
+    /* cosl(Inf) is NaN, cosl(0) is 1 */
+        else if (x + x == x && x != 0.0)
           return x-x;           /* NaN */
 
     /* argument reduction needed */
--- a/lib/ldexpl.c
+++ b/lib/ldexpl.c
@@ -25,6 +25,7 @@
 #include <math.h>
 
 #include <float.h>
+#include "isnanl.h"
 
 long double
 ldexpl(long double x, int exp)
@@ -33,7 +34,7 @@
   int bit;
 
   /* Check for zero, nan and infinity. */
-  if (x != x || x + x == x )
+  if (isnanl (x) || x + x == x)
     return x;
 
   if (exp < 0)
--- a/lib/logl.c
+++ b/lib/logl.c
@@ -64,6 +64,8 @@
  *
  */
 
+#include "isnanl.h"
+
 /* log(1+x) = x - .5 x^2 + x^3 l(x)
    -.0078125 <= x <= +.0078125
    peak relative error 1.2e-37 */
@@ -196,6 +198,11 @@
 
   /* Check for IEEE special cases.  */
 
+  /* log(NaN) = NaN. */
+  if (isnanl (x))
+    {
+      return x;
+    }
   /* log(0) = -infinity. */
   if (x == 0.0L)
     {
@@ -206,8 +213,8 @@
     {
       return (x - x) / ZERO;
     }
-  /* log (infinity or NaN) */
-  if (x + x == x || x != x)
+  /* log (infinity) */
+  if (x + x == x)
     {
       return x + x;
     }
--- a/lib/sinl.c
+++ b/lib/sinl.c
@@ -52,6 +52,7 @@
 #include "trigl.h"
 #include "trigl.c"
 #include "sincosl.c"
+#include "isnanl.h"
 
 long double
 sinl (long double x)
@@ -59,13 +60,17 @@
   long double y[2], z = 0.0L;
   int n;
 
+  /* sinl(NaN) is NaN */
+  if (isnanl (x))
+    return x;
+
   /* |x| ~< pi/4 */
   if (x >= -0.7853981633974483096156608458198757210492 &&
       x <= 0.7853981633974483096156608458198757210492)
     return kernel_sinl (x, z, 0);
 
-    /* sinl(Inf or NaN) is NaN, sinl(0) is 0 */
-  else if (x + x == x || x != x)
+    /* sinl(Inf) is NaN, sinl(0) is 0 */
+  else if (x + x == x)
     return x - x;		/* NaN */
 
   /* argument reduction needed */
--- a/lib/sqrtl.c
+++ b/lib/sqrtl.c
@@ -25,6 +25,7 @@
 #include <math.h>
 
 #include <float.h>
+#include "isnanl.h"
 
 /* A simple Newton-Raphson method. */
 long double
@@ -33,12 +34,16 @@
   long double delta, y;
   int exponent;
 
+  /* Check for NaN */
+  if (isnanl (x))
+    return x;
+
   /* Check for negative numbers */
   if (x < 0.0L)
     return (long double) sqrt(-1);
 
-  /* Check for zero, NANs and infinites */
-  if (x + x == x || x != x)
+  /* Check for zero and infinites */
+  if (x + x == x)
     return x;
 
   frexpl (x, &exponent);
--- a/lib/tanl.c
+++ b/lib/tanl.c
@@ -55,6 +55,7 @@
 #include "trigl.c"
 #endif
 #endif
+#include "isnanl.h"
 
 /*
  * ====================================================
@@ -191,13 +192,17 @@
   long double y[2], z = 0.0L;
   int n;
 
+  /* tanl(NaN) is NaN */
+  if (isnanl (x))
+    return x;
+
   /* |x| ~< pi/4 */
   if (x >= -0.7853981633974483096156608458198757210492 &&
       x <= 0.7853981633974483096156608458198757210492)
     return kernel_tanl (x, z, 1);
 
-  /* tanl(Inf or NaN) is NaN, tanl(0) is 0 */
-  else if (x + x == x || x != x)
+  /* tanl(Inf) is NaN, tanl(0) is 0 */
+  else if (x + x == x)
     return x - x;		/* NaN */
 
   /* argument reduction needed */
--- a/lib/trigl.c
+++ b/lib/trigl.c
@@ -233,7 +233,7 @@
 	return -1;
       }
 
-  if (x + x == x || x != x)	/* x is +=oo or NaN */
+  if (x + x == x)	/* x is ±oo */
     {
       y[0] = x - x;
       y[1] = y[0];