X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fisnan.c;h=a5ca38df4134c41a94528abc3341b59f3d1f671f;hb=2217763ff0775fa8093a26acfc1b51b726bb358a;hp=beeb98a50646190d16930b3e25477128b8b2aa36;hpb=0fd762677178fb5c3c75d811618431345206d541;p=gnulib.git
diff --git a/lib/isnan.c b/lib/isnan.c
index beeb98a50..a5ca38df4 100644
--- a/lib/isnan.c
+++ b/lib/isnan.c
@@ -1,19 +1,18 @@
/* Test for NaN that does not need libm.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2008 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
/* Written by Bruno Haible , 2007. */
@@ -22,6 +21,8 @@
#include
#include
+#include "float+.h"
+
#ifdef USE_LONG_DOUBLE
# define FUNC rpl_isnanl
# define DOUBLE long double
@@ -32,9 +33,10 @@
# define EXPBIT0_WORD LDBL_EXPBIT0_WORD
# define EXPBIT0_BIT LDBL_EXPBIT0_BIT
# endif
+# define SIZE SIZEOF_LDBL
# define L_(literal) literal##L
-#else
-# define FUNC rpl_isnan
+#elif ! defined USE_FLOAT
+# define FUNC rpl_isnand
# define DOUBLE double
# define MAX_EXP DBL_MAX_EXP
# define MIN_EXP DBL_MIN_EXP
@@ -43,7 +45,20 @@
# define EXPBIT0_WORD DBL_EXPBIT0_WORD
# define EXPBIT0_BIT DBL_EXPBIT0_BIT
# endif
+# define SIZE SIZEOF_DBL
# define L_(literal) literal
+#else /* defined USE_FLOAT */
+# define FUNC rpl_isnanf
+# define DOUBLE float
+# define MAX_EXP FLT_MAX_EXP
+# define MIN_EXP FLT_MIN_EXP
+# if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
+# define KNOWN_EXPBIT0_LOCATION
+# define EXPBIT0_WORD FLT_EXPBIT0_WORD
+# define EXPBIT0_BIT FLT_EXPBIT0_BIT
+# endif
+# define SIZE SIZEOF_FLT
+# define L_(literal) literal##f
#endif
#define EXP_MASK ((MAX_EXP - MIN_EXP) | 7)
@@ -56,20 +71,56 @@ int
FUNC (DOUBLE x)
{
#ifdef KNOWN_EXPBIT0_LOCATION
+# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+ /* Special CPU dependent code is needed to treat bit patterns outside the
+ IEEE 754 specification (such as Pseudo-NaNs, Pseudo-Infinities,
+ Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals) as NaNs.
+ These bit patterns are:
+ - exponent = 0x0001..0x7FFF, mantissa bit 63 = 0,
+ - exponent = 0x0000, mantissa bit 63 = 1.
+ The NaN bit pattern is:
+ - exponent = 0x7FFF, mantissa >= 0x8000000000000001. */
+ memory_double m;
+ unsigned int exponent;
+
+ m.value = x;
+ exponent = (m.word[EXPBIT0_WORD] >> EXPBIT0_BIT) & EXP_MASK;
+# ifdef WORDS_BIGENDIAN
+ /* Big endian: EXPBIT0_WORD = 0, EXPBIT0_BIT = 16. */
+ if (exponent == 0)
+ return 1 & (m.word[0] >> 15);
+ else if (exponent == EXP_MASK)
+ return (((m.word[0] ^ 0x8000U) << 16) | m.word[1] | (m.word[2] >> 16)) != 0;
+ else
+ return 1 & ~(m.word[0] >> 15);
+# else
+ /* Little endian: EXPBIT0_WORD = 2, EXPBIT0_BIT = 0. */
+ if (exponent == 0)
+ return (m.word[1] >> 31);
+ else if (exponent == EXP_MASK)
+ return ((m.word[1] ^ 0x80000000U) | m.word[0]) != 0;
+ else
+ return (m.word[1] >> 31) ^ 1;
+# endif
+# else
/* Be careful to not do any floating-point operation on x, such as x == x,
because x may be a signaling NaN. */
-# if defined __SUNPRO_C || defined __DECC
+# if defined __SUNPRO_C || defined __DECC || (defined __sgi && !defined __GNUC__)
/* The Sun C 5.0 compilers and the Compaq (ex-DEC) 6.4 compilers don't
- recognize the initializers as constant expressions. */
+ recognize the initializers as constant expressions. The latter compiler
+ also fails when constant-folding 0.0 / 0.0 even when constant-folding is
+ not required. The SGI MIPSpro C compiler complains about "floating-point
+ operation result is out of range". */
+ static DOUBLE zero = L_(0.0);
memory_double nan;
DOUBLE plus_inf = L_(1.0) / L_(0.0);
DOUBLE minus_inf = -L_(1.0) / L_(0.0);
- nan.value = L_(0.0) / L_(0.0);
-# else
+ nan.value = zero / zero;
+# else
static memory_double nan = { L_(0.0) / L_(0.0) };
static DOUBLE plus_inf = L_(1.0) / L_(0.0);
static DOUBLE minus_inf = -L_(1.0) / L_(0.0);
-# endif
+# endif
{
memory_double m;
@@ -79,16 +130,31 @@ FUNC (DOUBLE x)
if (((m.word[EXPBIT0_WORD] ^ nan.word[EXPBIT0_WORD])
& (EXP_MASK << EXPBIT0_BIT))
== 0)
- return (memcmp (&m.value, &plus_inf, sizeof (DOUBLE)) != 0
- && memcmp (&m.value, &minus_inf, sizeof (DOUBLE)) != 0);
+ return (memcmp (&m.value, &plus_inf, SIZE) != 0
+ && memcmp (&m.value, &minus_inf, SIZE) != 0);
else
return 0;
}
+# endif
#else
/* The configuration did not find sufficient information. Give up about
the signaling NaNs, handle only the quiet NaNs. */
if (x == x)
- return 0;
+ {
+# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+ /* Detect any special bit patterns that pass ==; see comment above. */
+ memory_double m1;
+ memory_double m2;
+
+ memset (&m1.value, 0, SIZE);
+ memset (&m2.value, 0, SIZE);
+ m1.value = x;
+ m2.value = x + (x ? 0.0L : -0.0L);
+ if (memcmp (&m1.value, &m2.value, SIZE) != 0)
+ return 1;
+# endif
+ return 0;
+ }
else
return 1;
#endif