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 == __BIG_ENDIAN
107 int sign_exponent
:16;
108 unsigned int empty
:16;
111 #elif __FLOAT_WORD_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__ = 33) && __LDBL_IS_IEC_60559__
142 /* Long double is 128-bit type. */
149 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
152 #elif __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
157 } ieee854_long_double_shape_type
;
160 __issignalingl (long double x
)
163 ieee854_long_double_shape_type u
;
169 hxi
^= UINT64_C (0x0000800000000000);
170 hxi
|= (lxi
| -lxi
) >> 63;
171 return (hxi
& UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
177 __issignalingl (long double x
)
185 #if __FLT128_IS_IEC_60559__
187 /* We have a _Float128 type. */
194 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
197 #elif __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
202 } ieee854_float128_shape_type
;
205 __issignalingf128 (__float128 x
)
208 ieee854_float128_shape_type u
;
214 hxi
^= UINT64_C (0x0000800000000000);
215 hxi
|= (lxi
| -lxi
) >> 63;
216 return (hxi
& UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
222 /* Define the type-generic macro based on the functions above. */
224 #if __FLT128_IS_IEC_60559__
225 # define issignaling(X) \
227 __float128: __issignalingf128, \
228 float: __issignalingf, \
229 double: __issignaling, \
230 long double: __issignalingl)(X)
232 # define issignaling(X) \
234 float: __issignalingf, \
235 double: __issignaling, \
236 long double: __issignalingl)(X)