1 /* Fallback implementation of issignaling macro.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
28 /* This header provides an implementation of the type-generic issignaling macro.
31 - This header is only included if the issignaling macro is not defined.
32 - All targets for which Fortran IEEE modules are supported currently have
33 the high-order bit of the NaN mantissa clear for signaling (and set
34 for quiet), as recommended by IEEE.
35 - We use the __*_IS_IEC_60559__ macros to make sure we only deal with formats
36 we know. For other floating-point formats, we consider all NaNs as quiet.
44 } ieee_float_shape_type
;
47 __issignalingf (float x
)
49 #if __FLT_IS_IEC_60559__
51 ieee_float_shape_type u
;
57 return (xi
& 0x7fffffff) > 0x7fc00000;
68 } ieee_double_shape_type
;
71 __issignaling (double x
)
73 #if __DBL_IS_IEC_60559__
74 ieee_double_shape_type u
;
80 xi
^= UINT64_C (0x0008000000000000);
81 return (xi
& UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7ff8000000000000);
88 #if __LDBL_DIG__ == __DBL_DIG__
90 /* Long double is the same as double. */
92 __issignalingl (long double x
)
94 return __issignaling (x
);
97 #elif (__LDBL_DIG__ == 18) && __LDBL_IS_IEC_60559__
99 /* Long double is x86 extended type. */
106 #if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
107 int sign_exponent
:16;
108 unsigned int empty
:16;
111 #elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
114 int sign_exponent
:16;
115 unsigned int empty
:16;
118 } ieee_long_double_shape_type
;
121 __issignalingl (long double x
)
124 uint32_t exi
, hxi
, lxi
;
125 ieee_long_double_shape_type u
;
128 exi
= u
.parts
.sign_exponent
;
132 /* Pseudo numbers on x86 are always signaling. */
133 ret
= (exi
& 0x7fff) && ((hxi
& 0x80000000) == 0);
136 hxi
|= (lxi
| -lxi
) >> 31;
137 return ret
|| (((exi
& 0x7fff) == 0x7fff) && (hxi
> 0xc0000000));
140 #elif (__LDBL_DIG__ == 31)
142 /* Long double is 128-bit IBM extended type. */
145 __issignalingl (long double x
)
147 union { long double value
; double parts
[2]; } u
;
150 return __issignaling (u
.parts
[0]);
153 #elif (__LDBL_DIG__ == 33) && __LDBL_IS_IEC_60559__
155 /* Long double is 128-bit type. */
162 #if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
165 #elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
170 } ieee854_long_double_shape_type
;
173 __issignalingl (long double x
)
176 ieee854_long_double_shape_type u
;
182 hxi
^= UINT64_C (0x0000800000000000);
183 hxi
|= (lxi
| -lxi
) >> 63;
184 return (hxi
& UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
190 __issignalingl (long double x
)
198 #if defined(GFC_REAL_16_IS_FLOAT128)
200 /* We have a _Float128 type. */
207 #if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
210 #elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
215 } ieee854_float128_shape_type
;
218 __issignalingf128 (_Float128 x
)
221 ieee854_float128_shape_type u
;
227 hxi
^= UINT64_C (0x0000800000000000);
228 hxi
|= (lxi
| -lxi
) >> 63;
229 return (hxi
& UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
235 /* Define the type-generic macro based on the functions above. */
237 #if defined(GFC_REAL_16_IS_FLOAT128)
238 # define issignaling(X) \
240 _Float128: __issignalingf128, \
241 float: __issignalingf, \
242 double: __issignaling, \
243 long double: __issignalingl)(X)
245 # define issignaling(X) \
247 float: __issignalingf, \
248 double: __issignaling, \
249 long double: __issignalingl)(X)