# HG changeset patch # User Bruno Haible # Date 1174947965 0 # Node ID c3d3347089284373e7187b8b87afd78aa1f24975 # Parent 6fd01943c239b9ddc586813d1bba3fb3e94482bd Better support of signalling NaNs. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2007-03-26 Bruno Haible + + 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 * m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_DIRECTIVE_A): Fix diff --git a/lib/atanl.c b/lib/atanl.c --- 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) { diff --git a/lib/cosl.c b/lib/cosl.c --- 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 */ diff --git a/lib/ldexpl.c b/lib/ldexpl.c --- a/lib/ldexpl.c +++ b/lib/ldexpl.c @@ -25,6 +25,7 @@ #include #include +#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) diff --git a/lib/logl.c b/lib/logl.c --- 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; } diff --git a/lib/sinl.c b/lib/sinl.c --- 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 */ diff --git a/lib/sqrtl.c b/lib/sqrtl.c --- a/lib/sqrtl.c +++ b/lib/sqrtl.c @@ -25,6 +25,7 @@ #include #include +#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); diff --git a/lib/tanl.c b/lib/tanl.c --- 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 */ diff --git a/lib/trigl.c b/lib/trigl.c --- 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];