LCOV - code coverage report
Current view: top level - lib - isnan.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 5 8 62.5 %
Date: 2018-01-30 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /* Test for NaN that does not need libm.
       2             :    Copyright (C) 2007-2008 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation; either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #include <float.h>
      22             : #include <string.h>
      23             : 
      24             : #include "float+.h"
      25             : 
      26             : #ifdef USE_LONG_DOUBLE
      27             : # define FUNC rpl_isnanl
      28             : # define DOUBLE long double
      29             : # define MAX_EXP LDBL_MAX_EXP
      30             : # define MIN_EXP LDBL_MIN_EXP
      31             : # if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
      32             : #  define KNOWN_EXPBIT0_LOCATION
      33             : #  define EXPBIT0_WORD LDBL_EXPBIT0_WORD
      34             : #  define EXPBIT0_BIT LDBL_EXPBIT0_BIT
      35             : # endif
      36             : # define SIZE SIZEOF_LDBL
      37             : # define L_(literal) literal##L
      38             : #elif ! defined USE_FLOAT
      39             : # define FUNC rpl_isnand
      40             : # define DOUBLE double
      41             : # define MAX_EXP DBL_MAX_EXP
      42             : # define MIN_EXP DBL_MIN_EXP
      43             : # if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
      44             : #  define KNOWN_EXPBIT0_LOCATION
      45             : #  define EXPBIT0_WORD DBL_EXPBIT0_WORD
      46             : #  define EXPBIT0_BIT DBL_EXPBIT0_BIT
      47             : # endif
      48             : # define SIZE SIZEOF_DBL
      49             : # define L_(literal) literal
      50             : #else /* defined USE_FLOAT */
      51             : # define FUNC rpl_isnanf
      52             : # define DOUBLE float
      53             : # define MAX_EXP FLT_MAX_EXP
      54             : # define MIN_EXP FLT_MIN_EXP
      55             : # if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
      56             : #  define KNOWN_EXPBIT0_LOCATION
      57             : #  define EXPBIT0_WORD FLT_EXPBIT0_WORD
      58             : #  define EXPBIT0_BIT FLT_EXPBIT0_BIT
      59             : # endif
      60             : # define SIZE SIZEOF_FLT
      61             : # define L_(literal) literal##f
      62             : #endif
      63             : 
      64             : #define EXP_MASK ((MAX_EXP - MIN_EXP) | 7)
      65             : 
      66             : #define NWORDS \
      67             :   ((sizeof (DOUBLE) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
      68             : typedef union { DOUBLE value; unsigned int word[NWORDS]; } memory_double;
      69             : 
      70             : int
      71          18 : FUNC (DOUBLE x)
      72             : {
      73             : #ifdef KNOWN_EXPBIT0_LOCATION
      74             : # 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_))
      75             :   /* Special CPU dependent code is needed to treat bit patterns outside the
      76             :      IEEE 754 specification (such as Pseudo-NaNs, Pseudo-Infinities,
      77             :      Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals) as NaNs.
      78             :      These bit patterns are:
      79             :        - exponent = 0x0001..0x7FFF, mantissa bit 63 = 0,
      80             :        - exponent = 0x0000, mantissa bit 63 = 1.
      81             :      The NaN bit pattern is:
      82             :        - exponent = 0x7FFF, mantissa >= 0x8000000000000001.  */
      83             :   memory_double m;
      84             :   unsigned int exponent;
      85             : 
      86          18 :   m.value = x;
      87          18 :   exponent = (m.word[EXPBIT0_WORD] >> EXPBIT0_BIT) & EXP_MASK;
      88             : #  ifdef WORDS_BIGENDIAN
      89             :   /* Big endian: EXPBIT0_WORD = 0, EXPBIT0_BIT = 16.  */
      90             :   if (exponent == 0)
      91             :     return 1 & (m.word[0] >> 15);
      92             :   else if (exponent == EXP_MASK)
      93             :     return (((m.word[0] ^ 0x8000U) << 16) | m.word[1] | (m.word[2] >> 16)) != 0;
      94             :   else
      95             :     return 1 & ~(m.word[0] >> 15);
      96             : #  else
      97             :   /* Little endian: EXPBIT0_WORD = 2, EXPBIT0_BIT = 0.  */
      98          18 :   if (exponent == 0)
      99          18 :     return (m.word[1] >> 31);
     100           0 :   else if (exponent == EXP_MASK)
     101           0 :     return ((m.word[1] ^ 0x80000000U) | m.word[0]) != 0;
     102             :   else
     103           0 :     return (m.word[1] >> 31) ^ 1;
     104             : #  endif
     105             : # else
     106             :   /* Be careful to not do any floating-point operation on x, such as x == x,
     107             :      because x may be a signaling NaN.  */
     108             : #  if defined __SUNPRO_C || defined __DECC || (defined __sgi && !defined __GNUC__)
     109             :   /* The Sun C 5.0 compilers and the Compaq (ex-DEC) 6.4 compilers don't
     110             :      recognize the initializers as constant expressions.  The latter compiler
     111             :      also fails when constant-folding 0.0 / 0.0 even when constant-folding is
     112             :      not required.  The SGI MIPSpro C compiler complains about "floating-point
     113             :      operation result is out of range".  */
     114             :   static DOUBLE zero = L_(0.0);
     115             :   memory_double nan;
     116             :   DOUBLE plus_inf = L_(1.0) / L_(0.0);
     117             :   DOUBLE minus_inf = -L_(1.0) / L_(0.0);
     118             :   nan.value = zero / zero;
     119             : #  else
     120             :   static memory_double nan = { L_(0.0) / L_(0.0) };
     121             :   static DOUBLE plus_inf = L_(1.0) / L_(0.0);
     122             :   static DOUBLE minus_inf = -L_(1.0) / L_(0.0);
     123             : #  endif
     124             :   {
     125             :     memory_double m;
     126             : 
     127             :     /* A NaN can be recognized through its exponent.  But exclude +Infinity and
     128             :        -Infinity, which have the same exponent.  */
     129             :     m.value = x;
     130             :     if (((m.word[EXPBIT0_WORD] ^ nan.word[EXPBIT0_WORD])
     131             :          & (EXP_MASK << EXPBIT0_BIT))
     132             :         == 0)
     133             :       return (memcmp (&m.value, &plus_inf, SIZE) != 0
     134             :               && memcmp (&m.value, &minus_inf, SIZE) != 0);
     135             :     else
     136             :       return 0;
     137             :   }
     138             : # endif
     139             : #else
     140             :   /* The configuration did not find sufficient information.  Give up about
     141             :      the signaling NaNs, handle only the quiet NaNs.  */
     142             :   if (x == x)
     143             :     {
     144             : # 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_))
     145             :       /* Detect any special bit patterns that pass ==; see comment above.  */
     146             :       memory_double m1;
     147             :       memory_double m2;
     148             : 
     149             :       memset (&m1.value, 0, SIZE);
     150             :       memset (&m2.value, 0, SIZE);
     151             :       m1.value = x;
     152             :       m2.value = x + (x ? 0.0L : -0.0L);
     153             :       if (memcmp (&m1.value, &m2.value, SIZE) != 0)
     154             :         return 1;
     155             : # endif
     156             :       return 0;
     157             :     }
     158             :   else
     159             :     return 1;
     160             : #endif
     161             : }

Generated by: LCOV version 1.10