diff options
Diffstat (limited to 'lib/isnan.c')
| -rw-r--r-- | lib/isnan.c | 46 | 
1 files changed, 31 insertions, 15 deletions
| diff --git a/lib/isnan.c b/lib/isnan.c index a59dea79..d70c9348 100644 --- a/lib/isnan.c +++ b/lib/isnan.c @@ -1,5 +1,5 @@  /* Test for NaN that does not need libm. -   Copyright (C) 2007-2010 Free Software Foundation, Inc. +   Copyright (C) 2007-2015 Free Software Foundation, Inc.     This program is free software: you can redistribute it and/or modify     it under the terms of the GNU Lesser General Public License as published by @@ -21,7 +21,7 @@  /* Specification.  */  #ifdef USE_LONG_DOUBLE  /* Specification found in math.h or isnanl-nolibm.h.  */ -extern int rpl_isnanl (long double x); +extern int rpl_isnanl (long double x) _GL_ATTRIBUTE_CONST;  #elif ! defined USE_FLOAT  /* Specification found in math.h or isnand-nolibm.h.  */  extern int rpl_isnand (double x); @@ -79,11 +79,22 @@ extern int rpl_isnanf (float x);    ((sizeof (DOUBLE) + sizeof (unsigned int) - 1) / sizeof (unsigned int))  typedef union { DOUBLE value; unsigned int word[NWORDS]; } memory_double; +/* Most hosts nowadays use IEEE floating point, so they use IEC 60559 +   representations, have infinities and NaNs, and do not trap on +   exceptions.  Define IEEE_FLOATING_POINT if this host is one of the +   typical ones.  The C11 macro __STDC_IEC_559__ is close to what is +   wanted here, but is not quite right because this file does not require +   all the features of C11 Annex F (and does not require C11 at all, +   for that matter).  */ + +#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \ +                             && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128) +  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_)) +#if defined KNOWN_EXPBIT0_LOCATION && IEEE_FLOATING_POINT +# 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_)) && !HAVE_SAME_LONG_DOUBLE_AS_DOUBLE    /* 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. @@ -117,16 +128,20 @@ FUNC (DOUBLE x)  # 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 || (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.  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".  */ +#  if defined __SUNPRO_C || defined __ICC || defined _MSC_VER \ +      || defined __DECC || defined __TINYC__ \ +      || (defined __sgi && !defined __GNUC__) +  /* The Sun C 5.0, Intel ICC 10.0, Microsoft Visual C/C++ 9.0, Compaq (ex-DEC) +     6.4, and TinyCC compilers don't recognize the initializers as constant +     expressions.  The Compaq compiler also fails when constant-folding +     0.0 / 0.0 even when constant-folding is not required.  The Microsoft +     Visual C/C++ compiler also fails when constant-folding 1.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); +  DOUBLE plus_inf = L_(1.0) / zero; +  DOUBLE minus_inf = -L_(1.0) / zero;    nan.value = zero / zero;  #  else    static memory_double nan = { L_(0.0) / L_(0.0) }; @@ -149,11 +164,12 @@ FUNC (DOUBLE x)    }  # endif  #else -  /* The configuration did not find sufficient information.  Give up about -     the signaling NaNs, handle only the quiet NaNs.  */ +  /* The configuration did not find sufficient information, or does +     not use IEEE floating point.  Give up about the signaling NaNs; +     handle only the quiet NaNs.  */    if (x == x)      { -# 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_)) +# 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_)) && !HAVE_SAME_LONG_DOUBLE_AS_DOUBLE        /* Detect any special bit patterns that pass ==; see comment above.  */        memory_double m1;        memory_double m2; | 
