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 float8 float_overflow_error_ext(struct Node *escontext);
37 : extern float8 float_underflow_error_ext(struct Node *escontext);
38 : extern float8 float_zero_divide_error_ext(struct Node *escontext);
39 : extern int is_infinite(float8 val);
40 : extern float8 float8in_internal(char *num, char **endptr_p,
41 : const char *type_name, const char *orig_string,
42 : struct Node *escontext);
43 : extern float4 float4in_internal(char *num, char **endptr_p,
44 : const char *type_name, const char *orig_string,
45 : struct Node *escontext);
46 : extern char *float8out_internal(float8 num);
47 : extern int float4_cmp_internal(float4 a, float4 b);
48 : extern int float8_cmp_internal(float8 a, float8 b);
49 :
50 : /*
51 : * Postgres requires IEEE-standard float arithmetic, including infinities
52 : * and NaNs. We used to support pre-C99 compilers on which <math.h> might
53 : * not supply the standard macros INFINITY and NAN. We no longer do so,
54 : * but these wrapper functions are still preferred over using those macros
55 : * directly.
56 : *
57 : * If you change these functions, see copies in interfaces/ecpg/ecpglib/data.c.
58 : */
59 :
60 : static inline float4
61 214263 : get_float4_infinity(void)
62 : {
63 : /* C99 standard way */
64 214263 : return (float4) INFINITY;
65 : }
66 :
67 : static inline float8
68 999924 : get_float8_infinity(void)
69 : {
70 : /* C99 standard way */
71 999924 : return (float8) INFINITY;
72 : }
73 :
74 : /* The C standard allows implementations to omit NAN, but we don't */
75 : #ifndef NAN
76 : #error "Postgres requires support for IEEE quiet NaNs"
77 : #endif
78 :
79 : static inline float4
80 22 : get_float4_nan(void)
81 : {
82 : /* C99 standard way */
83 22 : return (float4) NAN;
84 : }
85 :
86 : static inline float8
87 1526 : get_float8_nan(void)
88 : {
89 : /* C99 standard way */
90 1526 : return (float8) NAN;
91 : }
92 :
93 : /*
94 : * Floating-point arithmetic with overflow/underflow reported as errors
95 : *
96 : * There isn't any way to check for underflow of addition/subtraction
97 : * because numbers near the underflow value have already been rounded to
98 : * the point where we can't detect that the two values were originally
99 : * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
100 : * 1.4013e-45.
101 : */
102 :
103 : static inline float4
104 36 : float4_pl(const float4 val1, const float4 val2)
105 : {
106 : float4 result;
107 :
108 36 : result = val1 + val2;
109 36 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
110 0 : float_overflow_error();
111 :
112 36 : return result;
113 : }
114 :
115 : static inline float8
116 3842902 : float8_pl_safe(const float8 val1, const float8 val2, struct Node *escontext)
117 : {
118 : float8 result;
119 :
120 3842902 : result = val1 + val2;
121 3842902 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
122 0 : return float_overflow_error_ext(escontext);
123 :
124 3842902 : return result;
125 : }
126 :
127 : static inline float8
128 3332482 : float8_pl(const float8 val1, const float8 val2)
129 : {
130 3332482 : return float8_pl_safe(val1, val2, NULL);
131 : }
132 :
133 : static inline float4
134 12 : float4_mi(const float4 val1, const float4 val2)
135 : {
136 : float4 result;
137 :
138 12 : result = val1 - val2;
139 12 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
140 0 : float_overflow_error();
141 :
142 12 : return result;
143 : }
144 :
145 : static inline float8
146 173373204 : float8_mi_safe(const float8 val1, const float8 val2, struct Node *escontext)
147 : {
148 : float8 result;
149 :
150 173373204 : result = val1 - val2;
151 173373204 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
152 0 : return float_overflow_error_ext(escontext);
153 :
154 173373204 : return result;
155 : }
156 :
157 : static inline float8
158 152163654 : float8_mi(const float8 val1, const float8 val2)
159 : {
160 152163654 : return float8_mi_safe(val1, val2, NULL);
161 : }
162 :
163 : static inline float4
164 24 : float4_mul(const float4 val1, const float4 val2)
165 : {
166 : float4 result;
167 :
168 24 : result = val1 * val2;
169 24 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
170 0 : float_overflow_error();
171 24 : if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
172 0 : float_underflow_error();
173 :
174 24 : return result;
175 : }
176 :
177 : static inline float8
178 75304554 : float8_mul_safe(const float8 val1, const float8 val2, struct Node *escontext)
179 : {
180 : float8 result;
181 :
182 75304554 : result = val1 * val2;
183 75304554 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
184 16 : return float_overflow_error_ext(escontext);
185 75304538 : if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
186 4 : return float_underflow_error_ext(escontext);
187 :
188 75304534 : return result;
189 : }
190 :
191 : static inline float8
192 73863078 : float8_mul(const float8 val1, const float8 val2)
193 : {
194 73863078 : return float8_mul_safe(val1, val2, NULL);
195 : }
196 :
197 : static inline float4
198 4620738 : float4_div(const float4 val1, const float4 val2)
199 : {
200 : float4 result;
201 :
202 4620738 : if (unlikely(val2 == 0.0f) && !isnan(val1))
203 4 : float_zero_divide_error();
204 4620734 : result = val1 / val2;
205 4620734 : if (unlikely(isinf(result)) && !isinf(val1))
206 0 : float_overflow_error();
207 4620734 : if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
208 0 : float_underflow_error();
209 :
210 4620734 : return result;
211 : }
212 :
213 : static inline float8
214 12914387 : float8_div_safe(const float8 val1, const float8 val2, struct Node *escontext)
215 : {
216 : float8 result;
217 :
218 12914387 : if (unlikely(val2 == 0.0) && !isnan(val1))
219 44 : return float_zero_divide_error_ext(escontext);
220 12914343 : result = val1 / val2;
221 12914343 : if (unlikely(isinf(result)) && !isinf(val1))
222 0 : return float_overflow_error_ext(escontext);
223 12914343 : if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
224 0 : return float_underflow_error_ext(escontext);
225 :
226 12914343 : return result;
227 : }
228 :
229 : static inline float8
230 12888611 : float8_div(const float8 val1, const float8 val2)
231 : {
232 12888611 : return float8_div_safe(val1, val2, NULL);
233 : }
234 :
235 : /*
236 : * Routines for NaN-aware comparisons
237 : *
238 : * We consider all NaNs to be equal and larger than any non-NaN. This is
239 : * somewhat arbitrary; the important thing is to have a consistent sort
240 : * order.
241 : */
242 :
243 : static inline bool
244 24366 : float4_eq(const float4 val1, const float4 val2)
245 : {
246 24366 : return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
247 : }
248 :
249 : static inline bool
250 11321706 : float8_eq(const float8 val1, const float8 val2)
251 : {
252 11321706 : return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
253 : }
254 :
255 : static inline bool
256 20 : float4_ne(const float4 val1, const float4 val2)
257 : {
258 20 : return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
259 : }
260 :
261 : static inline bool
262 21788 : float8_ne(const float8 val1, const float8 val2)
263 : {
264 21788 : return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
265 : }
266 :
267 : static inline bool
268 8597305 : float4_lt(const float4 val1, const float4 val2)
269 : {
270 8597305 : return !isnan(val1) && (isnan(val2) || val1 < val2);
271 : }
272 :
273 : static inline bool
274 82651367 : float8_lt(const float8 val1, const float8 val2)
275 : {
276 82651367 : return !isnan(val1) && (isnan(val2) || val1 < val2);
277 : }
278 :
279 : static inline bool
280 2552 : float4_le(const float4 val1, const float4 val2)
281 : {
282 2552 : return isnan(val2) || (!isnan(val1) && val1 <= val2);
283 : }
284 :
285 : static inline bool
286 113202529 : float8_le(const float8 val1, const float8 val2)
287 : {
288 113202529 : return isnan(val2) || (!isnan(val1) && val1 <= val2);
289 : }
290 :
291 : static inline bool
292 8795160 : float4_gt(const float4 val1, const float4 val2)
293 : {
294 8795160 : return !isnan(val2) && (isnan(val1) || val1 > val2);
295 : }
296 :
297 : static inline bool
298 88247083 : float8_gt(const float8 val1, const float8 val2)
299 : {
300 88247083 : return !isnan(val2) && (isnan(val1) || val1 > val2);
301 : }
302 :
303 : static inline bool
304 2552 : float4_ge(const float4 val1, const float4 val2)
305 : {
306 2552 : return isnan(val1) || (!isnan(val2) && val1 >= val2);
307 : }
308 :
309 : static inline bool
310 5184916 : float8_ge(const float8 val1, const float8 val2)
311 : {
312 5184916 : return isnan(val1) || (!isnan(val2) && val1 >= val2);
313 : }
314 :
315 : static inline float4
316 : float4_min(const float4 val1, const float4 val2)
317 : {
318 : return float4_lt(val1, val2) ? val1 : val2;
319 : }
320 :
321 : static inline float8
322 62281676 : float8_min(const float8 val1, const float8 val2)
323 : {
324 62281676 : return float8_lt(val1, val2) ? val1 : val2;
325 : }
326 :
327 : static inline float4
328 : float4_max(const float4 val1, const float4 val2)
329 : {
330 : return float4_gt(val1, val2) ? val1 : val2;
331 : }
332 :
333 : static inline float8
334 62281676 : float8_max(const float8 val1, const float8 val2)
335 : {
336 62281676 : return float8_gt(val1, val2) ? val1 : val2;
337 : }
338 :
339 : #endif /* FLOAT_H */
|