summaryrefslogtreecommitdiffstats
path: root/gl/float.in.h
diff options
context:
space:
mode:
Diffstat (limited to 'gl/float.in.h')
-rw-r--r--gl/float.in.h236
1 files changed, 183 insertions, 53 deletions
diff --git a/gl/float.in.h b/gl/float.in.h
index 73e8d406..9f735cb9 100644
--- a/gl/float.in.h
+++ b/gl/float.in.h
@@ -1,6 +1,6 @@
1/* A correct <float.h>. 1/* A correct <float.h>.
2 2
3 Copyright (C) 2007-2024 Free Software Foundation, Inc. 3 Copyright (C) 2007-2026 Free Software Foundation, Inc.
4 4
5 This file is free software: you can redistribute it and/or modify 5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as 6 it under the terms of the GNU Lesser General Public License as
@@ -28,6 +28,8 @@
28#ifndef _@GUARD_PREFIX@_FLOAT_H 28#ifndef _@GUARD_PREFIX@_FLOAT_H
29#define _@GUARD_PREFIX@_FLOAT_H 29#define _@GUARD_PREFIX@_FLOAT_H
30 30
31/* ============================ ISO C99 support ============================ */
32
31/* 'long double' properties. */ 33/* 'long double' properties. */
32 34
33#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) 35#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
@@ -113,71 +115,199 @@ extern const union gl_long_double_union gl_LDBL_MAX;
113 115
114/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are 116/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are
115 wrong. 117 wrong.
116 On Linux/PowerPC with gcc 4.4, the value of LDBL_MAX is wrong. */ 118 On Linux/PowerPC with gcc 8.3, the values of LDBL_MAX and LDBL_EPSILON are
117#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__ 119 wrong.
120 Assume these bugs are fixed in any GCC new enough
121 to define __LDBL_NORM_MAX__. */
122#if (defined _ARCH_PPC && LDBL_MANT_DIG == 106 \
123 && defined __GNUC__ && !defined __LDBL_NORM_MAX__)
118# undef LDBL_MIN_EXP 124# undef LDBL_MIN_EXP
119# define LDBL_MIN_EXP DBL_MIN_EXP 125# define LDBL_MIN_EXP (-968)
120# undef LDBL_MIN_10_EXP 126# undef LDBL_MIN_10_EXP
121# define LDBL_MIN_10_EXP DBL_MIN_10_EXP 127# define LDBL_MIN_10_EXP (-291)
122# undef LDBL_MIN 128# undef LDBL_MIN
123# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ 129# define LDBL_MIN 0x1p-969L
124#endif 130
125#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ 131/* IBM long double is tricky: it is represented as the sum of two doubles,
132 and the high double must equal the sum of the two parts rounded to nearest.
133 The maximum finite value for which this is true is
134 { 0x1.fffffffffffffp+1023, 0x1.ffffffffffffep+969 },
135 which represents 0x1.fffffffffffff7ffffffffffff8p+1023L.
136 Although computations can yield representations of numbers larger than this,
137 these computations are considered to have overflowed and behavior is undefined.
138 See <https://gcc.gnu.org/PR120993>. */
126# undef LDBL_MAX 139# undef LDBL_MAX
127/* LDBL_MAX is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xFFFFFFFF }. 140# define LDBL_MAX 0x1.fffffffffffff7ffffffffffff8p+1023L
128 It is not easy to define:
129 #define LDBL_MAX 1.79769313486231580793728971405302307166e308L
130 is too small, whereas
131 #define LDBL_MAX 1.79769313486231580793728971405302307167e308L
132 is too large. Apparently a bug in GCC decimal-to-binary conversion.
133 Also, I can't get values larger than
134 #define LDBL63 ((long double) (1ULL << 63))
135 #define LDBL882 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63)
136 #define LDBL945 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63)
137 #define LDBL1008 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63)
138 #define LDBL_MAX (LDBL1008 * 65535.0L + LDBL945 * (long double) 9223372036821221375ULL + LDBL882 * (long double) 4611686018427387904ULL)
139 which is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xF8000000 }.
140 So, define it like this through a reference to an external variable
141 141
142 const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }; 142/* On PowerPC platforms, 'long double' has a double-double representation.
143 extern const long double LDBL_MAX; 143 Up to ISO C 17, this was outside the scope of ISO C because it can represent
144 numbers with mantissas of the form 1.<52 bits><many zeroes><52 bits>, such as
145 1.0L + 4.94065645841246544176568792868221e-324L = 1 + 2^-1074; see
146 ISO C 17 § 5.2.4.2.2.(3).
147 In ISO C 23, wording has been included that makes this 'long double'
148 representation compliant; see ISO C 23 § 5.2.5.3.3.(8)-(9). In this setting,
149 numbers with mantissas of the form 1.<52 bits><many zeroes><52 bits> are
150 called "unnormalized". And since LDBL_EPSILON must be normalized (per
151 ISO C 23 § 5.2.5.3.3.(33)), it must be 2^-105. */
152# undef LDBL_EPSILON
153# define LDBL_EPSILON 0x1p-105L
154#endif
144 155
145 or through a pointer cast 156/* ============================ ISO C11 support ============================ */
146 157
147 #define LDBL_MAX \ 158/* 'float' properties */
148 (*(const long double *) (double[]) { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL })
149 159
150 Unfortunately, this is not a constant expression, and the latter expression 160#ifndef FLT_HAS_SUBNORM
151 does not work well when GCC is optimizing.. */ 161# define FLT_HAS_SUBNORM 1
152# if !GNULIB_defined_long_double_union 162#endif
153union gl_long_double_union 163#ifndef FLT_DECIMAL_DIG
154 { 164/* FLT_MANT_DIG = 24 => FLT_DECIMAL_DIG = 9 */
155 struct { double hi; double lo; } dd; 165# define FLT_DECIMAL_DIG ((int)(FLT_MANT_DIG * 0.3010299956639812 + 2))
156 long double ld; 166#endif
157 }; 167#if defined _AIX && !defined __GNUC__
158# define GNULIB_defined_long_double_union 1 168/* On AIX, the value of FLT_TRUE_MIN in /usr/include/float.h is a 'double',
169 not a 'float'. */
170# undef FLT_TRUE_MIN
171#endif
172#ifndef FLT_TRUE_MIN
173/* FLT_MIN / 2^(FLT_MANT_DIG-1) */
174# define FLT_TRUE_MIN (FLT_MIN / 8388608.0f)
175#endif
176
177/* 'double' properties */
178
179#ifndef DBL_HAS_SUBNORM
180# define DBL_HAS_SUBNORM 1
181#endif
182#ifndef DBL_DECIMAL_DIG
183/* DBL_MANT_DIG = 53 => DBL_DECIMAL_DIG = 17 */
184# define DBL_DECIMAL_DIG ((int)(DBL_MANT_DIG * 0.3010299956639812 + 2))
185#endif
186#ifndef DBL_TRUE_MIN
187/* DBL_MIN / 2^(DBL_MANT_DIG-1) */
188# define DBL_TRUE_MIN (DBL_MIN / 4503599627370496.0)
189#endif
190
191/* 'long double' properties */
192
193#ifndef LDBL_HAS_SUBNORM
194# define LDBL_HAS_SUBNORM 1
195#endif
196#ifndef LDBL_DECIMAL_DIG
197/* LDBL_MANT_DIG = 53 => LDBL_DECIMAL_DIG = 17 */
198/* LDBL_MANT_DIG = 64 => LDBL_DECIMAL_DIG = 21 */
199/* LDBL_MANT_DIG = 106 => LDBL_DECIMAL_DIG = 33 */
200/* LDBL_MANT_DIG = 113 => LDBL_DECIMAL_DIG = 36 */
201# define LDBL_DECIMAL_DIG ((int)(LDBL_MANT_DIG * 0.3010299956639812 + 2))
202#endif
203#ifndef LDBL_TRUE_MIN
204/* LDBL_MIN / 2^(LDBL_MANT_DIG-1) */
205# if LDBL_MANT_DIG == 53
206# define LDBL_TRUE_MIN (LDBL_MIN / 4503599627370496.0L)
207# elif LDBL_MANT_DIG == 64
208# if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
209/* Work around FreeBSD/x86 problem mentioned above. */
210extern const union gl_long_double_union gl_LDBL_TRUE_MIN;
211# define LDBL_TRUE_MIN (gl_LDBL_TRUE_MIN.ld)
212# else
213# define LDBL_TRUE_MIN (LDBL_MIN / 9223372036854775808.0L)
214# endif
215# elif LDBL_MANT_DIG == 106
216# define LDBL_TRUE_MIN (LDBL_MIN / 40564819207303340847894502572032.0L)
217# elif LDBL_MANT_DIG == 113
218# define LDBL_TRUE_MIN (LDBL_MIN / 5192296858534827628530496329220096.0L)
159# endif 219# endif
160extern const union gl_long_double_union gl_LDBL_MAX;
161# define LDBL_MAX (gl_LDBL_MAX.ld)
162#endif 220#endif
163 221
164/* On IRIX 6.5, with cc, the value of LDBL_MANT_DIG is wrong. 222/* ============================ ISO C23 support ============================ */
165 On IRIX 6.5, with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_EPSILON 223
166 are wrong. */ 224/* 'float' properties */
167#if defined __sgi && (LDBL_MANT_DIG >= 106) 225
168# undef LDBL_MANT_DIG 226#ifndef FLT_IS_IEC_60559
169# define LDBL_MANT_DIG 106 227# if defined __m68k__
170# if defined __GNUC__ 228# define FLT_IS_IEC_60559 0
171# undef LDBL_MIN_EXP 229# else
172# define LDBL_MIN_EXP DBL_MIN_EXP 230# define FLT_IS_IEC_60559 1
173# undef LDBL_MIN_10_EXP 231# endif
174# define LDBL_MIN_10_EXP DBL_MIN_10_EXP 232#endif
175# undef LDBL_MIN 233#ifndef FLT_NORM_MAX
176# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ 234# define FLT_NORM_MAX FLT_MAX
177# undef LDBL_EPSILON 235#endif
178# define LDBL_EPSILON 2.46519032881566189191165176650870696773e-32L /* 2^-105 */ 236#ifndef FLT_SNAN
237/* For sh, beware of <https://gcc.gnu.org/PR111814>. */
238# if ((__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__) && !defined __sh__
239# define FLT_SNAN __builtin_nansf ("")
240# else
241typedef union { unsigned int word[1]; float value; } gl_FLT_SNAN_t;
242extern gl_FLT_SNAN_t gl_FLT_SNAN;
243# define FLT_SNAN (gl_FLT_SNAN.value)
244# define GNULIB_defined_FLT_SNAN 1
245# endif
246#endif
247
248/* 'double' properties */
249
250#ifndef DBL_IS_IEC_60559
251# if defined __m68k__
252# define DBL_IS_IEC_60559 0
253# else
254# define DBL_IS_IEC_60559 1
179# endif 255# endif
180#endif 256#endif
257#ifndef DBL_NORM_MAX
258# define DBL_NORM_MAX DBL_MAX
259#endif
260#ifndef DBL_SNAN
261/* For sh, beware of <https://gcc.gnu.org/PR111814>. */
262# if ((__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__) && !defined __sh__
263# define DBL_SNAN __builtin_nans ("")
264# else
265typedef union { unsigned long long word[1]; double value; } gl_DBL_SNAN_t;
266extern gl_DBL_SNAN_t gl_DBL_SNAN;
267# define DBL_SNAN (gl_DBL_SNAN.value)
268# define GNULIB_defined_DBL_SNAN 1
269# endif
270#endif
271
272/* 'long double' properties */
273
274#ifndef LDBL_IS_IEC_60559
275# if defined __m68k__
276# define LDBL_IS_IEC_60559 0
277# elif LDBL_MANT_DIG == 53 || LDBL_MANT_DIG == 113
278# define LDBL_IS_IEC_60559 1
279# else
280# define LDBL_IS_IEC_60559 0
281# endif
282#endif
283#ifndef LDBL_NORM_MAX
284# ifdef __LDBL_NORM_MAX__
285# define LDBL_NORM_MAX __LDBL_NORM_MAX__
286# elif FLT_RADIX == 2 && LDBL_MAX_EXP == 1024 && LDBL_MANT_DIG == 106
287# define LDBL_NORM_MAX 0x1.ffffffffffffffffffffffffff8p+1022L
288# else
289# define LDBL_NORM_MAX LDBL_MAX
290# endif
291#endif
292#ifndef LDBL_SNAN
293/* For sh, beware of <https://gcc.gnu.org/PR111814>. */
294# if ((__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__) && !defined __sh__
295# define LDBL_SNAN __builtin_nansl ("")
296# else
297# if LDBL_MANT_DIG == 53
298typedef union { unsigned long long word[1]; long double value; } gl_LDBL_SNAN_t;
299# elif defined __m68k__
300typedef union { unsigned int word[3]; long double value; } gl_LDBL_SNAN_t;
301# else
302typedef union { unsigned long long word[2]; long double value; } gl_LDBL_SNAN_t;
303# endif
304extern gl_LDBL_SNAN_t gl_LDBL_SNAN;
305# define LDBL_SNAN (gl_LDBL_SNAN.value)
306# define GNULIB_defined_LDBL_SNAN 1
307# endif
308#endif
309
310/* ================================= Other ================================= */
181 311
182#if @REPLACE_ITOLD@ 312#if @REPLACE_ITOLD@
183/* Pull in a function that fixes the 'int' to 'long double' conversion 313/* Pull in a function that fixes the 'int' to 'long double' conversion