gettext: Sync with gettext 0.23.
[gnulib.git] / lib / signed-nan.h
blobcae6c5d504bbc50648cc438b47252ffd5c968bf5
1 /* Macros for quiet not-a-number.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #ifndef _SIGNED_NAN_H
18 #define _SIGNED_NAN_H
20 #include <math.h>
22 #include "nan.h"
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
29 /* Returns - x, implemented by inverting the sign bit,
30 so that it works also on 'float' NaN values. */
31 _GL_UNUSED static float
32 minus_NaNf (float x)
34 #if defined __mips__
35 /* The mips instruction neg.s may have no effect on NaNs.
36 Therefore, invert the sign bit using integer operations. */
37 union { unsigned int i; float value; } u;
38 u.value = x;
39 u.i ^= 1U << 31;
40 return u.value;
41 #else
42 return - x;
43 #endif
46 /* Returns a quiet 'float' NaN with sign bit == 0. */
47 _GL_UNUSED static float
48 positive_NaNf ()
50 /* 'volatile' works around a GCC bug:
51 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655> */
52 float volatile nan = NaNf ();
53 return (signbit (nan) ? minus_NaNf (nan) : nan);
56 /* Returns a quiet 'float' NaN with sign bit == 1. */
57 _GL_UNUSED static float
58 negative_NaNf ()
60 /* 'volatile' works around a GCC bug:
61 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655> */
62 float volatile nan = NaNf ();
63 return (signbit (nan) ? nan : minus_NaNf (nan));
67 /* Returns - x, implemented by inverting the sign bit,
68 so that it works also on 'double' NaN values. */
69 _GL_UNUSED static double
70 minus_NaNd (double x)
72 #if defined __mips__
73 /* The mips instruction neg.d may have no effect on NaNs.
74 Therefore, invert the sign bit using integer operations. */
75 union { unsigned long long i; double value; } u;
76 u.value = x;
77 u.i ^= 1ULL << 63;
78 return u.value;
79 #else
80 return - x;
81 #endif
84 /* Returns a quiet 'double' NaN with sign bit == 0. */
85 _GL_UNUSED static double
86 positive_NaNd ()
88 /* 'volatile' works around a GCC bug:
89 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655> */
90 double volatile nan = NaNd ();
91 return (signbit (nan) ? minus_NaNd (nan) : nan);
94 /* Returns a quiet 'double' NaN with sign bit == 1. */
95 _GL_UNUSED static double
96 negative_NaNd ()
98 /* 'volatile' works around a GCC bug:
99 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655> */
100 double volatile nan = NaNd ();
101 return (signbit (nan) ? nan : minus_NaNd (nan));
105 /* Returns - x, implemented by inverting the sign bit,
106 so that it works also on 'long double' NaN values. */
107 _GL_UNUSED static long double
108 minus_NaNl (long double x)
110 return - x;
113 /* Returns a quiet 'long double' NaN with sign bit == 0. */
114 _GL_UNUSED static long double
115 positive_NaNl ()
117 /* 'volatile' works around a GCC bug:
118 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655> */
119 long double volatile nan = NaNl ();
120 return (signbit (nan) ? minus_NaNl (nan) : nan);
123 /* Returns a quiet 'long double' NaN with sign bit == 1. */
124 _GL_UNUSED static long double
125 negative_NaNl ()
127 /* 'volatile' works around a GCC bug:
128 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655> */
129 long double volatile nan = NaNl ();
130 return (signbit (nan) ? nan : minus_NaNl (nan));
134 #ifdef __cplusplus
136 #endif
138 #endif /* _SIGNED_NAN_H */