1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * float.h |
4 | * Definitions for the built-in floating-point types |
5 | * |
6 | * Portions Copyright (c) 1996-2019, 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 | #ifndef M_PI |
21 | /* From my RH5.2 gcc math.h file - thomas 2000-04-03 */ |
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 | /* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */ |
29 | #if defined(WIN32) && !defined(NAN) |
30 | static const uint32 nan[2] = {0xffffffff, 0x7fffffff}; |
31 | |
32 | #define NAN (*(const float8 *) nan) |
33 | #endif |
34 | |
35 | extern PGDLLIMPORT int ; |
36 | |
37 | /* |
38 | * Utility functions in float.c |
39 | */ |
40 | extern int is_infinite(float8 val); |
41 | extern float8 float8in_internal(char *num, char **endptr_p, |
42 | const char *type_name, const char *orig_string); |
43 | extern float8 float8in_internal_opt_error(char *num, char **endptr_p, |
44 | const char *type_name, const char *orig_string, |
45 | bool *have_error); |
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 | * Routines to provide reasonably platform-independent handling of |
52 | * infinity and NaN |
53 | * |
54 | * We assume that isinf() and isnan() are available and work per spec. |
55 | * (On some platforms, we have to supply our own; see src/port.) However, |
56 | * generating an Infinity or NaN in the first place is less well standardized; |
57 | * pre-C99 systems tend not to have C99's INFINITY and NaN macros. We |
58 | * centralize our workarounds for this here. |
59 | */ |
60 | |
61 | /* |
62 | * The funny placements of the two #pragmas is necessary because of a |
63 | * long lived bug in the Microsoft compilers. |
64 | * See http://support.microsoft.com/kb/120968/en-us for details |
65 | */ |
66 | #if (_MSC_VER >= 1800) |
67 | #pragma warning(disable:4756) |
68 | #endif |
69 | static inline float4 |
70 | get_float4_infinity(void) |
71 | { |
72 | #ifdef INFINITY |
73 | /* C99 standard way */ |
74 | return (float4) INFINITY; |
75 | #else |
76 | #if (_MSC_VER >= 1800) |
77 | #pragma warning(default:4756) |
78 | #endif |
79 | |
80 | /* |
81 | * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the |
82 | * largest normal float8. We assume forcing an overflow will get us a |
83 | * true infinity. |
84 | */ |
85 | return (float4) (HUGE_VAL * HUGE_VAL); |
86 | #endif |
87 | } |
88 | |
89 | static inline float8 |
90 | get_float8_infinity(void) |
91 | { |
92 | #ifdef INFINITY |
93 | /* C99 standard way */ |
94 | return (float8) INFINITY; |
95 | #else |
96 | |
97 | /* |
98 | * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the |
99 | * largest normal float8. We assume forcing an overflow will get us a |
100 | * true infinity. |
101 | */ |
102 | return (float8) (HUGE_VAL * HUGE_VAL); |
103 | #endif |
104 | } |
105 | |
106 | static inline float4 |
107 | get_float4_nan(void) |
108 | { |
109 | #ifdef NAN |
110 | /* C99 standard way */ |
111 | return (float4) NAN; |
112 | #else |
113 | /* Assume we can get a NAN via zero divide */ |
114 | return (float4) (0.0 / 0.0); |
115 | #endif |
116 | } |
117 | |
118 | static inline float8 |
119 | get_float8_nan(void) |
120 | { |
121 | /* (float8) NAN doesn't work on some NetBSD/MIPS releases */ |
122 | #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__)) |
123 | /* C99 standard way */ |
124 | return (float8) NAN; |
125 | #else |
126 | /* Assume we can get a NaN via zero divide */ |
127 | return (float8) (0.0 / 0.0); |
128 | #endif |
129 | } |
130 | |
131 | /* |
132 | * Checks to see if a float4/8 val has underflowed or overflowed |
133 | */ |
134 | |
135 | static inline void |
136 | check_float4_val(const float4 val, const bool inf_is_valid, |
137 | const bool zero_is_valid) |
138 | { |
139 | if (!inf_is_valid && unlikely(isinf(val))) |
140 | ereport(ERROR, |
141 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
142 | errmsg("value out of range: overflow" ))); |
143 | |
144 | if (!zero_is_valid && unlikely(val == 0.0)) |
145 | ereport(ERROR, |
146 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
147 | errmsg("value out of range: underflow" ))); |
148 | } |
149 | |
150 | static inline void |
151 | check_float8_val(const float8 val, const bool inf_is_valid, |
152 | const bool zero_is_valid) |
153 | { |
154 | if (!inf_is_valid && unlikely(isinf(val))) |
155 | ereport(ERROR, |
156 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
157 | errmsg("value out of range: overflow" ))); |
158 | |
159 | if (!zero_is_valid && unlikely(val == 0.0)) |
160 | ereport(ERROR, |
161 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
162 | errmsg("value out of range: underflow" ))); |
163 | } |
164 | |
165 | /* |
166 | * Routines for operations with the checks above |
167 | * |
168 | * There isn't any way to check for underflow of addition/subtraction |
169 | * because numbers near the underflow value have already been rounded to |
170 | * the point where we can't detect that the two values were originally |
171 | * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 == |
172 | * 1.4013e-45. |
173 | */ |
174 | |
175 | static inline float4 |
176 | float4_pl(const float4 val1, const float4 val2) |
177 | { |
178 | float4 result; |
179 | |
180 | result = val1 + val2; |
181 | check_float4_val(result, isinf(val1) || isinf(val2), true); |
182 | |
183 | return result; |
184 | } |
185 | |
186 | static inline float8 |
187 | float8_pl(const float8 val1, const float8 val2) |
188 | { |
189 | float8 result; |
190 | |
191 | result = val1 + val2; |
192 | check_float8_val(result, isinf(val1) || isinf(val2), true); |
193 | |
194 | return result; |
195 | } |
196 | |
197 | static inline float4 |
198 | float4_mi(const float4 val1, const float4 val2) |
199 | { |
200 | float4 result; |
201 | |
202 | result = val1 - val2; |
203 | check_float4_val(result, isinf(val1) || isinf(val2), true); |
204 | |
205 | return result; |
206 | } |
207 | |
208 | static inline float8 |
209 | float8_mi(const float8 val1, const float8 val2) |
210 | { |
211 | float8 result; |
212 | |
213 | result = val1 - val2; |
214 | check_float8_val(result, isinf(val1) || isinf(val2), true); |
215 | |
216 | return result; |
217 | } |
218 | |
219 | static inline float4 |
220 | float4_mul(const float4 val1, const float4 val2) |
221 | { |
222 | float4 result; |
223 | |
224 | result = val1 * val2; |
225 | check_float4_val(result, isinf(val1) || isinf(val2), |
226 | val1 == 0.0f || val2 == 0.0f); |
227 | |
228 | return result; |
229 | } |
230 | |
231 | static inline float8 |
232 | float8_mul(const float8 val1, const float8 val2) |
233 | { |
234 | float8 result; |
235 | |
236 | result = val1 * val2; |
237 | check_float8_val(result, isinf(val1) || isinf(val2), |
238 | val1 == 0.0 || val2 == 0.0); |
239 | |
240 | return result; |
241 | } |
242 | |
243 | static inline float4 |
244 | float4_div(const float4 val1, const float4 val2) |
245 | { |
246 | float4 result; |
247 | |
248 | if (val2 == 0.0f) |
249 | ereport(ERROR, |
250 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
251 | errmsg("division by zero" ))); |
252 | |
253 | result = val1 / val2; |
254 | check_float4_val(result, isinf(val1) || isinf(val2), val1 == 0.0f); |
255 | |
256 | return result; |
257 | } |
258 | |
259 | static inline float8 |
260 | float8_div(const float8 val1, const float8 val2) |
261 | { |
262 | float8 result; |
263 | |
264 | if (val2 == 0.0) |
265 | ereport(ERROR, |
266 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
267 | errmsg("division by zero" ))); |
268 | |
269 | result = val1 / val2; |
270 | check_float8_val(result, isinf(val1) || isinf(val2), val1 == 0.0); |
271 | |
272 | return result; |
273 | } |
274 | |
275 | /* |
276 | * Routines for NaN-aware comparisons |
277 | * |
278 | * We consider all NaNs to be equal and larger than any non-NaN. This is |
279 | * somewhat arbitrary; the important thing is to have a consistent sort |
280 | * order. |
281 | */ |
282 | |
283 | static inline bool |
284 | float4_eq(const float4 val1, const float4 val2) |
285 | { |
286 | return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2; |
287 | } |
288 | |
289 | static inline bool |
290 | float8_eq(const float8 val1, const float8 val2) |
291 | { |
292 | return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2; |
293 | } |
294 | |
295 | static inline bool |
296 | float4_ne(const float4 val1, const float4 val2) |
297 | { |
298 | return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2; |
299 | } |
300 | |
301 | static inline bool |
302 | float8_ne(const float8 val1, const float8 val2) |
303 | { |
304 | return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2; |
305 | } |
306 | |
307 | static inline bool |
308 | float4_lt(const float4 val1, const float4 val2) |
309 | { |
310 | return !isnan(val1) && (isnan(val2) || val1 < val2); |
311 | } |
312 | |
313 | static inline bool |
314 | float8_lt(const float8 val1, const float8 val2) |
315 | { |
316 | return !isnan(val1) && (isnan(val2) || val1 < val2); |
317 | } |
318 | |
319 | static inline bool |
320 | float4_le(const float4 val1, const float4 val2) |
321 | { |
322 | return isnan(val2) || (!isnan(val1) && val1 <= val2); |
323 | } |
324 | |
325 | static inline bool |
326 | float8_le(const float8 val1, const float8 val2) |
327 | { |
328 | return isnan(val2) || (!isnan(val1) && val1 <= val2); |
329 | } |
330 | |
331 | static inline bool |
332 | float4_gt(const float4 val1, const float4 val2) |
333 | { |
334 | return !isnan(val2) && (isnan(val1) || val1 > val2); |
335 | } |
336 | |
337 | static inline bool |
338 | float8_gt(const float8 val1, const float8 val2) |
339 | { |
340 | return !isnan(val2) && (isnan(val1) || val1 > val2); |
341 | } |
342 | |
343 | static inline bool |
344 | float4_ge(const float4 val1, const float4 val2) |
345 | { |
346 | return isnan(val1) || (!isnan(val2) && val1 >= val2); |
347 | } |
348 | |
349 | static inline bool |
350 | float8_ge(const float8 val1, const float8 val2) |
351 | { |
352 | return isnan(val1) || (!isnan(val2) && val1 >= val2); |
353 | } |
354 | |
355 | static inline float4 |
356 | float4_min(const float4 val1, const float4 val2) |
357 | { |
358 | return float4_lt(val1, val2) ? val1 : val2; |
359 | } |
360 | |
361 | static inline float8 |
362 | float8_min(const float8 val1, const float8 val2) |
363 | { |
364 | return float8_lt(val1, val2) ? val1 : val2; |
365 | } |
366 | |
367 | static inline float4 |
368 | float4_max(const float4 val1, const float4 val2) |
369 | { |
370 | return float4_gt(val1, val2) ? val1 : val2; |
371 | } |
372 | |
373 | static inline float8 |
374 | float8_max(const float8 val1, const float8 val2) |
375 | { |
376 | return float8_gt(val1, val2) ? val1 : val2; |
377 | } |
378 | |
379 | #endif /* FLOAT_H */ |
380 | |