Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * float.h
4 : * Definitions for the built-in floating-point types
5 : *
6 : * Portions Copyright (c) 1996-2025, 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 352086 : get_float4_infinity(void)
59 : {
60 : /* C99 standard way */
61 352086 : return (float4) INFINITY;
62 : }
63 :
64 : static inline float8
65 1507162 : get_float8_infinity(void)
66 : {
67 : /* C99 standard way */
68 1507162 : 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 30 : get_float4_nan(void)
78 : {
79 : /* C99 standard way */
80 30 : return (float4) NAN;
81 : }
82 :
83 : static inline float8
84 21732 : get_float8_nan(void)
85 : {
86 : /* C99 standard way */
87 21732 : 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 54 : float4_pl(const float4 val1, const float4 val2)
102 : {
103 : float4 result;
104 :
105 54 : result = val1 + val2;
106 54 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
107 0 : float_overflow_error();
108 :
109 54 : return result;
110 : }
111 :
112 : static inline float8
113 5785444 : float8_pl(const float8 val1, const float8 val2)
114 : {
115 : float8 result;
116 :
117 5785444 : result = val1 + val2;
118 5785444 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
119 0 : float_overflow_error();
120 :
121 5785444 : return result;
122 : }
123 :
124 : static inline float4
125 18 : float4_mi(const float4 val1, const float4 val2)
126 : {
127 : float4 result;
128 :
129 18 : result = val1 - val2;
130 18 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
131 0 : float_overflow_error();
132 :
133 18 : return result;
134 : }
135 :
136 : static inline float8
137 260589610 : float8_mi(const float8 val1, const float8 val2)
138 : {
139 : float8 result;
140 :
141 260589610 : result = val1 - val2;
142 260589610 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
143 0 : float_overflow_error();
144 :
145 260589610 : return result;
146 : }
147 :
148 : static inline float4
149 36 : float4_mul(const float4 val1, const float4 val2)
150 : {
151 : float4 result;
152 :
153 36 : result = val1 * val2;
154 36 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
155 0 : float_overflow_error();
156 36 : if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
157 0 : float_underflow_error();
158 :
159 36 : return result;
160 : }
161 :
162 : static inline float8
163 113571346 : float8_mul(const float8 val1, const float8 val2)
164 : {
165 : float8 result;
166 :
167 113571346 : result = val1 * val2;
168 113571346 : if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
169 24 : float_overflow_error();
170 113571322 : if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
171 6 : float_underflow_error();
172 :
173 113571316 : return result;
174 : }
175 :
176 : static inline float4
177 7070720 : float4_div(const float4 val1, const float4 val2)
178 : {
179 : float4 result;
180 :
181 7070720 : if (unlikely(val2 == 0.0f) && !isnan(val1))
182 6 : float_zero_divide_error();
183 7070714 : result = val1 / val2;
184 7070714 : if (unlikely(isinf(result)) && !isinf(val1))
185 0 : float_overflow_error();
186 7070714 : if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
187 0 : float_underflow_error();
188 :
189 7070714 : return result;
190 : }
191 :
192 : static inline float8
193 19428368 : float8_div(const float8 val1, const float8 val2)
194 : {
195 : float8 result;
196 :
197 19428368 : if (unlikely(val2 == 0.0) && !isnan(val1))
198 66 : float_zero_divide_error();
199 19428302 : result = val1 / val2;
200 19428302 : if (unlikely(isinf(result)) && !isinf(val1))
201 0 : float_overflow_error();
202 19428302 : if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
203 0 : float_underflow_error();
204 :
205 19428302 : return result;
206 : }
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 44858 : float4_eq(const float4 val1, const float4 val2)
218 : {
219 44858 : return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
220 : }
221 :
222 : static inline bool
223 17318810 : float8_eq(const float8 val1, const float8 val2)
224 : {
225 17318810 : return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
226 : }
227 :
228 : static inline bool
229 30 : float4_ne(const float4 val1, const float4 val2)
230 : {
231 30 : return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
232 : }
233 :
234 : static inline bool
235 36492 : float8_ne(const float8 val1, const float8 val2)
236 : {
237 36492 : return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
238 : }
239 :
240 : static inline bool
241 14915178 : float4_lt(const float4 val1, const float4 val2)
242 : {
243 14915178 : return !isnan(val1) && (isnan(val2) || val1 < val2);
244 : }
245 :
246 : static inline bool
247 124324590 : float8_lt(const float8 val1, const float8 val2)
248 : {
249 124324590 : return !isnan(val1) && (isnan(val2) || val1 < val2);
250 : }
251 :
252 : static inline bool
253 3828 : float4_le(const float4 val1, const float4 val2)
254 : {
255 3828 : return isnan(val2) || (!isnan(val1) && val1 <= val2);
256 : }
257 :
258 : static inline bool
259 170313164 : float8_le(const float8 val1, const float8 val2)
260 : {
261 170313164 : return isnan(val2) || (!isnan(val1) && val1 <= val2);
262 : }
263 :
264 : static inline bool
265 15257988 : float4_gt(const float4 val1, const float4 val2)
266 : {
267 15257988 : return !isnan(val2) && (isnan(val1) || val1 > val2);
268 : }
269 :
270 : static inline bool
271 132515478 : float8_gt(const float8 val1, const float8 val2)
272 : {
273 132515478 : return !isnan(val2) && (isnan(val1) || val1 > val2);
274 : }
275 :
276 : static inline bool
277 3828 : float4_ge(const float4 val1, const float4 val2)
278 : {
279 3828 : return isnan(val1) || (!isnan(val2) && val1 >= val2);
280 : }
281 :
282 : static inline bool
283 7934596 : float8_ge(const float8 val1, const float8 val2)
284 : {
285 7934596 : 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 93589596 : float8_min(const float8 val1, const float8 val2)
296 : {
297 93589596 : 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 93589596 : float8_max(const float8 val1, const float8 val2)
308 : {
309 93589596 : return float8_gt(val1, val2) ? val1 : val2;
310 : }
311 :
312 : #endif /* FLOAT_H */
|