~ubuntu-branches/ubuntu/vivid/gzip/vivid

« back to all changes in this revision

Viewing changes to lib/isnan.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-10-19 11:42:42 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20111019114242-d8wiiu8kbvdtgmgj
Tags: 1.4-1ubuntu1
* Merge with Debian testing.  Remaining Ubuntu changes:
  - debian/{control,rules}: Remove the Win32 build and mingw64
    build-dependency, since mingw is in universe, and will remain so for
    the forseeable future.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Test for NaN that does not need libm.
 
2
   Copyright (C) 2007-2010 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
/* Specification.  */
 
22
#ifdef USE_LONG_DOUBLE
 
23
/* Specification found in math.h or isnanl-nolibm.h.  */
 
24
extern int rpl_isnanl (long double x);
 
25
#elif ! defined USE_FLOAT
 
26
/* Specification found in math.h or isnand-nolibm.h.  */
 
27
extern int rpl_isnand (double x);
 
28
#else /* defined USE_FLOAT */
 
29
/* Specification found in math.h or isnanf-nolibm.h.  */
 
30
extern int rpl_isnanf (float x);
 
31
#endif
 
32
 
 
33
#include <float.h>
 
34
#include <string.h>
 
35
 
 
36
#include "float+.h"
 
37
 
 
38
#ifdef USE_LONG_DOUBLE
 
39
# define FUNC rpl_isnanl
 
40
# define DOUBLE long double
 
41
# define MAX_EXP LDBL_MAX_EXP
 
42
# define MIN_EXP LDBL_MIN_EXP
 
43
# if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
 
44
#  define KNOWN_EXPBIT0_LOCATION
 
45
#  define EXPBIT0_WORD LDBL_EXPBIT0_WORD
 
46
#  define EXPBIT0_BIT LDBL_EXPBIT0_BIT
 
47
# endif
 
48
# define SIZE SIZEOF_LDBL
 
49
# define L_(literal) literal##L
 
50
#elif ! defined USE_FLOAT
 
51
# define FUNC rpl_isnand
 
52
# define DOUBLE double
 
53
# define MAX_EXP DBL_MAX_EXP
 
54
# define MIN_EXP DBL_MIN_EXP
 
55
# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
 
56
#  define KNOWN_EXPBIT0_LOCATION
 
57
#  define EXPBIT0_WORD DBL_EXPBIT0_WORD
 
58
#  define EXPBIT0_BIT DBL_EXPBIT0_BIT
 
59
# endif
 
60
# define SIZE SIZEOF_DBL
 
61
# define L_(literal) literal
 
62
#else /* defined USE_FLOAT */
 
63
# define FUNC rpl_isnanf
 
64
# define DOUBLE float
 
65
# define MAX_EXP FLT_MAX_EXP
 
66
# define MIN_EXP FLT_MIN_EXP
 
67
# if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
 
68
#  define KNOWN_EXPBIT0_LOCATION
 
69
#  define EXPBIT0_WORD FLT_EXPBIT0_WORD
 
70
#  define EXPBIT0_BIT FLT_EXPBIT0_BIT
 
71
# endif
 
72
# define SIZE SIZEOF_FLT
 
73
# define L_(literal) literal##f
 
74
#endif
 
75
 
 
76
#define EXP_MASK ((MAX_EXP - MIN_EXP) | 7)
 
77
 
 
78
#define NWORDS \
 
79
  ((sizeof (DOUBLE) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
 
80
typedef union { DOUBLE value; unsigned int word[NWORDS]; } memory_double;
 
81
 
 
82
int
 
83
FUNC (DOUBLE x)
 
84
{
 
85
#ifdef KNOWN_EXPBIT0_LOCATION
 
86
# 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_))
 
87
  /* Special CPU dependent code is needed to treat bit patterns outside the
 
88
     IEEE 754 specification (such as Pseudo-NaNs, Pseudo-Infinities,
 
89
     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals) as NaNs.
 
90
     These bit patterns are:
 
91
       - exponent = 0x0001..0x7FFF, mantissa bit 63 = 0,
 
92
       - exponent = 0x0000, mantissa bit 63 = 1.
 
93
     The NaN bit pattern is:
 
94
       - exponent = 0x7FFF, mantissa >= 0x8000000000000001.  */
 
95
  memory_double m;
 
96
  unsigned int exponent;
 
97
 
 
98
  m.value = x;
 
99
  exponent = (m.word[EXPBIT0_WORD] >> EXPBIT0_BIT) & EXP_MASK;
 
100
#  ifdef WORDS_BIGENDIAN
 
101
  /* Big endian: EXPBIT0_WORD = 0, EXPBIT0_BIT = 16.  */
 
102
  if (exponent == 0)
 
103
    return 1 & (m.word[0] >> 15);
 
104
  else if (exponent == EXP_MASK)
 
105
    return (((m.word[0] ^ 0x8000U) << 16) | m.word[1] | (m.word[2] >> 16)) != 0;
 
106
  else
 
107
    return 1 & ~(m.word[0] >> 15);
 
108
#  else
 
109
  /* Little endian: EXPBIT0_WORD = 2, EXPBIT0_BIT = 0.  */
 
110
  if (exponent == 0)
 
111
    return (m.word[1] >> 31);
 
112
  else if (exponent == EXP_MASK)
 
113
    return ((m.word[1] ^ 0x80000000U) | m.word[0]) != 0;
 
114
  else
 
115
    return (m.word[1] >> 31) ^ 1;
 
116
#  endif
 
117
# else
 
118
  /* Be careful to not do any floating-point operation on x, such as x == x,
 
119
     because x may be a signaling NaN.  */
 
120
#  if defined __SUNPRO_C || defined __DECC || (defined __sgi && !defined __GNUC__)
 
121
  /* The Sun C 5.0 compilers and the Compaq (ex-DEC) 6.4 compilers don't
 
122
     recognize the initializers as constant expressions.  The latter compiler
 
123
     also fails when constant-folding 0.0 / 0.0 even when constant-folding is
 
124
     not required.  The SGI MIPSpro C compiler complains about "floating-point
 
125
     operation result is out of range".  */
 
126
  static DOUBLE zero = L_(0.0);
 
127
  memory_double nan;
 
128
  DOUBLE plus_inf = L_(1.0) / L_(0.0);
 
129
  DOUBLE minus_inf = -L_(1.0) / L_(0.0);
 
130
  nan.value = zero / zero;
 
131
#  else
 
132
  static memory_double nan = { L_(0.0) / L_(0.0) };
 
133
  static DOUBLE plus_inf = L_(1.0) / L_(0.0);
 
134
  static DOUBLE minus_inf = -L_(1.0) / L_(0.0);
 
135
#  endif
 
136
  {
 
137
    memory_double m;
 
138
 
 
139
    /* A NaN can be recognized through its exponent.  But exclude +Infinity and
 
140
       -Infinity, which have the same exponent.  */
 
141
    m.value = x;
 
142
    if (((m.word[EXPBIT0_WORD] ^ nan.word[EXPBIT0_WORD])
 
143
         & (EXP_MASK << EXPBIT0_BIT))
 
144
        == 0)
 
145
      return (memcmp (&m.value, &plus_inf, SIZE) != 0
 
146
              && memcmp (&m.value, &minus_inf, SIZE) != 0);
 
147
    else
 
148
      return 0;
 
149
  }
 
150
# endif
 
151
#else
 
152
  /* The configuration did not find sufficient information.  Give up about
 
153
     the signaling NaNs, handle only the quiet NaNs.  */
 
154
  if (x == x)
 
155
    {
 
156
# 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_))
 
157
      /* Detect any special bit patterns that pass ==; see comment above.  */
 
158
      memory_double m1;
 
159
      memory_double m2;
 
160
 
 
161
      memset (&m1.value, 0, SIZE);
 
162
      memset (&m2.value, 0, SIZE);
 
163
      m1.value = x;
 
164
      m2.value = x + (x ? 0.0L : -0.0L);
 
165
      if (memcmp (&m1.value, &m2.value, SIZE) != 0)
 
166
        return 1;
 
167
# endif
 
168
      return 0;
 
169
    }
 
170
  else
 
171
    return 1;
 
172
#endif
 
173
}