exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / snan.h
blob95235040461c51169c3b750ea090b87401f39c24
1 /* Macros for signalling not-a-number.
2 Copyright (C) 2007-2024 Free Software Foundation, Inc.
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.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #ifndef _SNAN_H
18 #define _SNAN_H
20 #include <float.h>
21 #include <limits.h>
22 #include <math.h>
24 #include "nan.h"
27 /* The bit that distinguishes a quiet NaN from a signalling NaN is, according to
28 <https://en.wikipedia.org/wiki/NaN#Encoding>, the most significant bit of the
29 mantissa field.
30 According to <https://en.wikipedia.org/wiki/IEEE_754#Formats>, this is the
31 next bit, right below the bit 0 of the exponent.
32 This bit is
33 * == 0 to indicate a quiet NaN or Infinity,
34 == 1 to indicate a signalling NaN,
35 on these CPUs: hppa, mips (*), sh4.
36 * == 1 to indicate a quiet NaN,
37 == 0 to indicate a signalling NaN or Infinity,
38 on all other CPUs.
39 On these platforms, additionally a signalling NaN must have some other
40 mantissa bit == 1, because when all exponent bits are == 1 and all
41 mantissa bits are == 0, the number denotes ±Infinity.
42 This NaN encoding is specified by IEEE 754-2008 § 6.2.1.
44 (*) On mips CPUs, it depends on the CPU model. The classical behaviour is
45 as indicated above. On some newer models, it's like on the other CPUs.
46 On some (but not all!) models this meta-info can be determined from two
47 special CPU registers: If the "Floating Point Implementation Register" (fir)
48 bit 23, also known as Has2008 bit, is set, the "Floating Point Control and
49 Status Register" (fcsr) bit 18, also known as the NAN2008 bit, has the value
50 - 0 for the classical behaviour,
51 - 1 for like on the other CPUs.
52 Both of these bits are read-only.
53 This module has determined the behaviour at configure time and defines the
54 C macros MIPS_NAN2008_FLOAT, MIPS_NAN2008_DOUBLE, MIPS_NAN2008_LONG_DOUBLE
55 accordingly. */
58 /* 'float' = IEEE 754 single-precision
59 <https://en.wikipedia.org/wiki/Single-precision_floating-point_format> */
61 #define NWORDS \
62 ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
63 typedef union { float value; unsigned int word[NWORDS]; } memory_float;
65 #if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
67 # define HAVE_SNANF 1
69 _GL_UNUSED static memory_float
70 construct_memory_SNaNf (float quiet_value)
72 memory_float m;
73 m.value = quiet_value;
74 /* Turn the quiet NaN into a signalling NaN. */
75 #if FLT_EXPBIT0_BIT > 0
76 m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1);
77 #else
78 m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
79 ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
80 #endif
81 /* Set some arbitrary mantissa bit. */
82 if (FLT_EXPBIT0_WORD < NWORDS / 2) /* NWORDS > 1 and big endian */
83 m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT;
84 else /* NWORDS == 1 or little endian */
85 m.word[0] |= (unsigned int) 1;
86 return m;
89 /* Returns a signalling 'float' NaN in memory. */
90 _GL_UNUSED static memory_float
91 memory_SNaNf ()
93 return construct_memory_SNaNf (NaNf ());
96 _GL_UNUSED static float
97 construct_SNaNf (float quiet_value)
99 return construct_memory_SNaNf (quiet_value).value;
102 /* Returns a signalling 'float' NaN.
103 Note: On 32-bit x86 processors, as well as on x86_64 processors with
104 CC="gcc -mfpmath=387", this function may return a quiet NaN instead.
105 Use memory_SNaNf() if you need to avoid this. See
106 <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
107 for details. */
108 _GL_UNUSED static float
109 SNaNf ()
111 return memory_SNaNf ().value;
114 #endif
116 #undef NWORDS
119 /* 'double' = IEEE 754 double-precision
120 <https://en.wikipedia.org/wiki/Double-precision_floating-point_format> */
122 #define NWORDS \
123 ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
124 typedef union { double value; unsigned int word[NWORDS]; } memory_double;
126 #if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
128 # define HAVE_SNAND 1
130 _GL_UNUSED static memory_double
131 construct_memory_SNaNd (double quiet_value)
133 memory_double m;
134 m.value = quiet_value;
135 /* Turn the quiet NaN into a signalling NaN. */
136 #if DBL_EXPBIT0_BIT > 0
137 m.word[DBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (DBL_EXPBIT0_BIT - 1);
138 #else
139 m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
140 ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
141 #endif
142 /* Set some arbitrary mantissa bit. */
143 m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
144 |= (unsigned int) 1 << DBL_EXPBIT0_BIT;
145 return m;
148 /* Returns a signalling 'double' NaN in memory. */
149 _GL_UNUSED static memory_double
150 memory_SNaNd ()
152 return construct_memory_SNaNd (NaNd ());
155 _GL_UNUSED static double
156 construct_SNaNd (double quiet_value)
158 return construct_memory_SNaNd (quiet_value).value;
161 /* Returns a signalling 'double' NaN.
162 Note: On 32-bit x86 processors, as well as on x86_64 processors with
163 CC="gcc -mfpmath=387", this function may return a quiet NaN instead.
164 Use memory_SNaNf() if you need to avoid this. See
165 <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
166 for details. */
167 _GL_UNUSED static double
168 SNaNd ()
170 return memory_SNaNd ().value;
173 #endif
175 #undef NWORDS
178 /* 'long double' =
179 * if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE:
180 IEEE 754 double-precision
181 <https://en.wikipedia.org/wiki/Double-precision_floating-point_format>
182 * Otherwise:
183 - On i386, x86_64, ia64:
184 80-bits extended-precision
185 <https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format>
186 - On alpha, arm64, loongarch64, mips64, riscv64, s390x, sparc64:
187 IEEE 754 quadruple-precision
188 <https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#IEEE_754_quadruple-precision_binary_floating-point_format:_binary128>
189 - On powerpc, powerpc64, powerpc64le:
190 2x64-bits double-double
191 <https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic>
192 - On m68k:
193 80-bits extended-precision, padded to 96 bits, with non-IEEE exponent
196 #define NWORDS \
197 ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
198 typedef union { long double value; unsigned int word[NWORDS]; }
199 memory_long_double;
201 #if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
203 # define HAVE_SNANL 1
205 _GL_UNUSED static memory_long_double
206 construct_memory_SNaNl (long double quiet_value)
208 memory_long_double m;
209 m.value = quiet_value;
210 #if defined __powerpc__ && LDBL_MANT_DIG == 106
211 /* This is PowerPC "double double", a pair of two doubles. Inf and NaN are
212 represented as the corresponding 64-bit IEEE values in the first double;
213 the second is ignored. Manipulate only the first double. */
214 #define HNWORDS \
215 ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
216 #else
217 #define HNWORDS NWORDS
218 #endif
219 /* Turn the quiet NaN into a signalling NaN. */
220 #if ((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
221 /* In this representation, the leading 1 of the mantissa is explicitly
222 stored. */
223 #if LDBL_EXPBIT0_BIT > 1
224 m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 2);
225 #else
226 m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)]
227 ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 2);
228 #endif
229 #else
230 /* In this representation, the leading 1 of the mantissa is implicit. */
231 #if LDBL_EXPBIT0_BIT > 0
232 m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1);
233 #else
234 m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)]
235 ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
236 #endif
237 #endif
238 /* Set some arbitrary mantissa bit. */
239 m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)]
240 |= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
241 #undef HNWORDS
242 return m;
245 /* Returns a signalling 'long double' NaN in memory. */
246 _GL_UNUSED static memory_long_double
247 memory_SNaNl ()
249 return construct_memory_SNaNl (NaNl ());
252 _GL_UNUSED static long double
253 construct_SNaNl (long double quiet_value)
255 return construct_memory_SNaNl (quiet_value).value;
258 /* Returns a signalling 'long double' NaN.
259 Note: On 32-bit x86 processors, as well as on x86_64 processors with
260 CC="gcc -mfpmath=387", if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE is 1, this
261 function may return a quiet NaN instead. Use memory_SNaNf() if you
262 need to avoid this. See
263 <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
264 for details. */
265 _GL_UNUSED static long double
266 SNaNl ()
268 return memory_SNaNl ().value;
271 #endif
273 #undef NWORDS
276 #endif /* _SNAN_H */