Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * float.h
4 : : * Definitions for the built-in floating-point types
5 : : *
6 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/include/utils/float.h
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : #ifndef FLOAT_H
16 : : #define FLOAT_H
17 : :
18 : : #include <math.h>
19 : :
20 : : /* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
21 : : #ifndef M_PI
22 : : #define M_PI 3.14159265358979323846
23 : : #endif
24 : :
25 : : /* Radians per degree, a.k.a. PI / 180 */
26 : : #define RADIANS_PER_DEGREE 0.0174532925199432957692
27 : :
28 : : extern PGDLLIMPORT int extra_float_digits;
29 : :
30 : : /*
31 : : * Utility functions in float.c
32 : : */
33 : : pg_noreturn extern void float_overflow_error(void);
34 : : pg_noreturn extern void float_underflow_error(void);
35 : : pg_noreturn extern void float_zero_divide_error(void);
36 : : extern int is_infinite(float8 val);
37 : : extern float8 float8in_internal(char *num, char **endptr_p,
38 : : const char *type_name, const char *orig_string,
39 : : struct Node *escontext);
40 : : extern float4 float4in_internal(char *num, char **endptr_p,
41 : : const char *type_name, const char *orig_string,
42 : : struct Node *escontext);
43 : : extern char *float8out_internal(float8 num);
44 : : extern int float4_cmp_internal(float4 a, float4 b);
45 : : extern int float8_cmp_internal(float8 a, float8 b);
46 : :
47 : : /*
48 : : * Postgres requires IEEE-standard float arithmetic, including infinities
49 : : * and NaNs. We used to support pre-C99 compilers on which <math.h> might
50 : : * not supply the standard macros INFINITY and NAN. We no longer do so,
51 : : * but these wrapper functions are still preferred over using those macros
52 : : * directly.
53 : : *
54 : : * If you change these functions, see copies in interfaces/ecpg/ecpglib/data.c.
55 : : */
56 : :
57 : : static inline float4
58 : 41783 : get_float4_infinity(void)
59 : : {
60 : : /* C99 standard way */
61 : 41783 : return (float4) INFINITY;
62 : : }
63 : :
64 : : static inline float8
65 : 249857 : get_float8_infinity(void)
66 : : {
67 : : /* C99 standard way */
68 : 249857 : return (float8) INFINITY;
69 : : }
70 : :
71 : : /* The C standard allows implementations to omit NAN, but we don't */
72 : : #ifndef NAN
73 : : #error "Postgres requires support for IEEE quiet NaNs"
74 : : #endif
75 : :
76 : : static inline float4
77 : 5 : get_float4_nan(void)
78 : : {
79 : : /* C99 standard way */
80 : 5 : return (float4) NAN;
81 : : }
82 : :
83 : : static inline float8
84 : 378 : get_float8_nan(void)
85 : : {
86 : : /* C99 standard way */
87 : 378 : return (float8) NAN;
88 : : }
89 : :
90 : : /*
91 : : * Floating-point arithmetic with overflow/underflow reported as errors
92 : : *
93 : : * There isn't any way to check for underflow of addition/subtraction
94 : : * because numbers near the underflow value have already been rounded to
95 : : * the point where we can't detect that the two values were originally
96 : : * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
97 : : * 1.4013e-45.
98 : : */
99 : :
100 : : static inline float4
101 : 9 : float4_pl(const float4 val1, const float4 val2)
102 : : {
103 : 9 : float4 result;
104 : :
105 : 9 : result = val1 + val2;
106 [ - + # # : 9 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
# # ]
107 : 0 : float_overflow_error();
108 : :
109 : 18 : return result;
110 : 9 : }
111 : :
112 : : static inline float8
113 : 896173 : float8_pl(const float8 val1, const float8 val2)
114 : : {
115 : 896173 : float8 result;
116 : :
117 : 896173 : result = val1 + val2;
118 [ + + + + : 896173 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ - ]
119 : 0 : float_overflow_error();
120 : :
121 : 1792346 : return result;
122 : 896173 : }
123 : :
124 : : static inline float4
125 : 3 : float4_mi(const float4 val1, const float4 val2)
126 : : {
127 : 3 : float4 result;
128 : :
129 : 3 : result = val1 - val2;
130 [ - + # # : 3 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
# # ]
131 : 0 : float_overflow_error();
132 : :
133 : 6 : return result;
134 : 3 : }
135 : :
136 : : static inline float8
137 : 8800666 : float8_mi(const float8 val1, const float8 val2)
138 : : {
139 : 8800666 : float8 result;
140 : :
141 : 8800666 : result = val1 - val2;
142 [ + + + + : 8800666 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ - ]
143 : 0 : float_overflow_error();
144 : :
145 : 17601332 : return result;
146 : 8800666 : }
147 : :
148 : : static inline float4
149 : 6 : float4_mul(const float4 val1, const float4 val2)
150 : : {
151 : 6 : float4 result;
152 : :
153 : 6 : result = val1 * val2;
154 [ - + # # : 6 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
# # ]
155 : 0 : float_overflow_error();
156 [ - + # # : 6 : if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
# # ]
157 : 0 : float_underflow_error();
158 : :
159 : 12 : return result;
160 : 6 : }
161 : :
162 : : static inline float8
163 : 5168635 : float8_mul(const float8 val1, const float8 val2)
164 : : {
165 : 5168635 : float8 result;
166 : :
167 : 5168635 : result = val1 * val2;
168 [ + + + + : 5168635 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ + ]
169 : 4 : float_overflow_error();
170 [ + + + + : 5168631 : if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
+ + ]
171 : 1 : float_underflow_error();
172 : :
173 : 10337260 : return result;
174 : 5168630 : }
175 : :
176 : : static inline float4
177 : 8 : float4_div(const float4 val1, const float4 val2)
178 : : {
179 : 8 : float4 result;
180 : :
181 [ + + + - : 8 : if (unlikely(val2 == 0.0f) && !isnan(val1))
+ + # # ]
182 : 1 : float_zero_divide_error();
183 : 7 : result = val1 / val2;
184 [ - + # # ]: 7 : if (unlikely(isinf(result)) && !isinf(val1))
185 : 0 : float_overflow_error();
186 [ + + + - : 7 : if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
+ - ]
187 : 0 : float_underflow_error();
188 : :
189 : 14 : return result;
190 : 7 : }
191 : :
192 : : static inline float8
193 : 2762332 : float8_div(const float8 val1, const float8 val2)
194 : : {
195 : 2762332 : float8 result;
196 : :
197 [ + + - + : 2762332 : if (unlikely(val2 == 0.0) && !isnan(val1))
+ + + - ]
198 : 11 : float_zero_divide_error();
199 : 2762343 : result = val1 / val2;
200 [ + + + - ]: 2762343 : if (unlikely(isinf(result)) && !isinf(val1))
201 : 0 : float_overflow_error();
202 [ + + + + : 2762343 : if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
+ - ]
203 : 0 : float_underflow_error();
204 : :
205 : 5524686 : return result;
206 : 2762343 : }
207 : :
208 : : /*
209 : : * Routines for NaN-aware comparisons
210 : : *
211 : : * We consider all NaNs to be equal and larger than any non-NaN. This is
212 : : * somewhat arbitrary; the important thing is to have a consistent sort
213 : : * order.
214 : : */
215 : :
216 : : static inline bool
217 : 3722 : float4_eq(const float4 val1, const float4 val2)
218 : : {
219 [ + - + + : 3722 : return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
# # + - -
+ # # ]
220 : : }
221 : :
222 : : static inline bool
223 : 98673 : float8_eq(const float8 val1, const float8 val2)
224 : : {
225 [ - + + + : 98673 : return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
+ - - + +
+ + - ]
226 : : }
227 : :
228 : : static inline bool
229 : 5 : float4_ne(const float4 val1, const float4 val2)
230 : : {
231 [ + - - + : 5 : return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
# # + - -
+ # # ]
232 : : }
233 : :
234 : : static inline bool
235 : 3437 : float8_ne(const float8 val1, const float8 val2)
236 : : {
237 [ - + + + : 3437 : return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
+ - - + +
+ + - ]
238 : : }
239 : :
240 : : static inline bool
241 : 86150 : float4_lt(const float4 val1, const float4 val2)
242 : : {
243 [ + - + + : 172298 : return !isnan(val1) && (isnan(val2) || val1 < val2);
# # + - +
+ # # ]
244 : : }
245 : :
246 : : static inline bool
247 : 4895247 : float8_lt(const float8 val1, const float8 val2)
248 : : {
249 [ - + + + : 19578977 : return !isnan(val1) && (isnan(val2) || val1 < val2);
+ - - + +
+ + - ]
250 : : }
251 : :
252 : : static inline bool
253 : 638 : float4_le(const float4 val1, const float4 val2)
254 : : {
255 [ + - - + : 638 : return isnan(val2) || (!isnan(val1) && val1 <= val2);
# # + - -
+ # # ]
256 : : }
257 : :
258 : : static inline bool
259 : 5680 : float8_le(const float8 val1, const float8 val2)
260 : : {
261 [ - + + + : 5680 : return isnan(val2) || (!isnan(val1) && val1 <= val2);
+ - - + +
+ + - ]
262 : : }
263 : :
264 : : static inline bool
265 : 76539 : float4_gt(const float4 val1, const float4 val2)
266 : : {
267 [ + - + + : 153072 : return !isnan(val2) && (isnan(val1) || val1 > val2);
# # + - -
+ # # ]
268 : : }
269 : :
270 : : static inline bool
271 : 6209447 : float8_gt(const float8 val1, const float8 val2)
272 : : {
273 [ - + + + : 24836443 : return !isnan(val2) && (isnan(val1) || val1 > val2);
+ - - + +
+ + - ]
274 : : }
275 : :
276 : : static inline bool
277 : 638 : float4_ge(const float4 val1, const float4 val2)
278 : : {
279 [ + - - + : 638 : return isnan(val1) || (!isnan(val2) && val1 >= val2);
# # + - -
+ # # ]
280 : : }
281 : :
282 : : static inline bool
283 : 4530 : float8_ge(const float8 val1, const float8 val2)
284 : : {
285 [ - + + + : 4530 : return isnan(val1) || (!isnan(val2) && val1 >= val2);
+ - - + +
+ + - ]
286 : : }
287 : :
288 : : static inline float4
289 : : float4_min(const float4 val1, const float4 val2)
290 : : {
291 : : return float4_lt(val1, val2) ? val1 : val2;
292 : : }
293 : :
294 : : static inline float8
295 : 2147588 : float8_min(const float8 val1, const float8 val2)
296 : : {
297 [ + + ]: 2147588 : return float8_lt(val1, val2) ? val1 : val2;
298 : : }
299 : :
300 : : static inline float4
301 : : float4_max(const float4 val1, const float4 val2)
302 : : {
303 : : return float4_gt(val1, val2) ? val1 : val2;
304 : : }
305 : :
306 : : static inline float8
307 : 2147588 : float8_max(const float8 val1, const float8 val2)
308 : : {
309 [ + + ]: 2147588 : return float8_gt(val1, val2) ? val1 : val2;
310 : : }
311 : :
312 : : #endif /* FLOAT_H */
|