PostgreSQL Source Code  git master
float.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * float.h
4  * Definitions for the built-in floating-point types
5  *
6  * Portions Copyright (c) 1996-2023, 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 /* 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 
36 
37 /*
38  * Utility functions in float.c
39  */
43 extern int is_infinite(float8 val);
44 extern float8 float8in_internal(char *num, char **endptr_p,
45  const char *type_name, const char *orig_string,
46  struct Node *escontext);
47 extern float4 float4in_internal(char *num, char **endptr_p,
48  const char *type_name, const char *orig_string,
49  struct Node *escontext);
50 extern char *float8out_internal(float8 num);
51 extern int float4_cmp_internal(float4 a, float4 b);
52 extern int float8_cmp_internal(float8 a, float8 b);
53 
54 /*
55  * Routines to provide reasonably platform-independent handling of
56  * infinity and NaN
57  *
58  * We assume that isinf() and isnan() are available and work per spec.
59  * (On some platforms, we have to supply our own; see src/port.) However,
60  * generating an Infinity or NaN in the first place is less well standardized;
61  * pre-C99 systems tend not to have C99's INFINITY and NaN macros. We
62  * centralize our workarounds for this here.
63  */
64 
65 /*
66  * The funny placements of the two #pragmas is necessary because of a
67  * long lived bug in the Microsoft compilers.
68  * See http://support.microsoft.com/kb/120968/en-us for details
69  */
70 #ifdef _MSC_VER
71 #pragma warning(disable:4756)
72 #endif
73 static inline float4
75 {
76 #ifdef INFINITY
77  /* C99 standard way */
78  return (float4) INFINITY;
79 #else
80 #ifdef _MSC_VER
81 #pragma warning(default:4756)
82 #endif
83 
84  /*
85  * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
86  * largest normal float8. We assume forcing an overflow will get us a
87  * true infinity.
88  */
89  return (float4) (HUGE_VAL * HUGE_VAL);
90 #endif
91 }
92 
93 static inline float8
95 {
96 #ifdef INFINITY
97  /* C99 standard way */
98  return (float8) INFINITY;
99 #else
100 
101  /*
102  * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
103  * largest normal float8. We assume forcing an overflow will get us a
104  * true infinity.
105  */
106  return (float8) (HUGE_VAL * HUGE_VAL);
107 #endif
108 }
109 
110 static inline float4
112 {
113 #ifdef NAN
114  /* C99 standard way */
115  return (float4) NAN;
116 #else
117  /* Assume we can get a NAN via zero divide */
118  return (float4) (0.0 / 0.0);
119 #endif
120 }
121 
122 static inline float8
124 {
125  /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
126 #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
127  /* C99 standard way */
128  return (float8) NAN;
129 #else
130  /* Assume we can get a NaN via zero divide */
131  return (float8) (0.0 / 0.0);
132 #endif
133 }
134 
135 /*
136  * Floating-point arithmetic with overflow/underflow reported as errors
137  *
138  * There isn't any way to check for underflow of addition/subtraction
139  * because numbers near the underflow value have already been rounded to
140  * the point where we can't detect that the two values were originally
141  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
142  * 1.4013e-45.
143  */
144 
145 static inline float4
146 float4_pl(const float4 val1, const float4 val2)
147 {
148  float4 result;
149 
150  result = val1 + val2;
151  if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
153 
154  return result;
155 }
156 
157 static inline float8
158 float8_pl(const float8 val1, const float8 val2)
159 {
160  float8 result;
161 
162  result = val1 + val2;
163  if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
165 
166  return result;
167 }
168 
169 static inline float4
170 float4_mi(const float4 val1, const float4 val2)
171 {
172  float4 result;
173 
174  result = val1 - val2;
175  if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
177 
178  return result;
179 }
180 
181 static inline float8
182 float8_mi(const float8 val1, const float8 val2)
183 {
184  float8 result;
185 
186  result = val1 - val2;
187  if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
189 
190  return result;
191 }
192 
193 static inline float4
194 float4_mul(const float4 val1, const float4 val2)
195 {
196  float4 result;
197 
198  result = val1 * val2;
199  if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
201  if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
203 
204  return result;
205 }
206 
207 static inline float8
208 float8_mul(const float8 val1, const float8 val2)
209 {
210  float8 result;
211 
212  result = val1 * val2;
213  if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
215  if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
217 
218  return result;
219 }
220 
221 static inline float4
222 float4_div(const float4 val1, const float4 val2)
223 {
224  float4 result;
225 
226  if (unlikely(val2 == 0.0f) && !isnan(val1))
228  result = val1 / val2;
229  if (unlikely(isinf(result)) && !isinf(val1))
231  if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
233 
234  return result;
235 }
236 
237 static inline float8
238 float8_div(const float8 val1, const float8 val2)
239 {
240  float8 result;
241 
242  if (unlikely(val2 == 0.0) && !isnan(val1))
244  result = val1 / val2;
245  if (unlikely(isinf(result)) && !isinf(val1))
247  if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
249 
250  return result;
251 }
252 
253 /*
254  * Routines for NaN-aware comparisons
255  *
256  * We consider all NaNs to be equal and larger than any non-NaN. This is
257  * somewhat arbitrary; the important thing is to have a consistent sort
258  * order.
259  */
260 
261 static inline bool
262 float4_eq(const float4 val1, const float4 val2)
263 {
264  return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
265 }
266 
267 static inline bool
268 float8_eq(const float8 val1, const float8 val2)
269 {
270  return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
271 }
272 
273 static inline bool
274 float4_ne(const float4 val1, const float4 val2)
275 {
276  return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
277 }
278 
279 static inline bool
280 float8_ne(const float8 val1, const float8 val2)
281 {
282  return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
283 }
284 
285 static inline bool
286 float4_lt(const float4 val1, const float4 val2)
287 {
288  return !isnan(val1) && (isnan(val2) || val1 < val2);
289 }
290 
291 static inline bool
292 float8_lt(const float8 val1, const float8 val2)
293 {
294  return !isnan(val1) && (isnan(val2) || val1 < val2);
295 }
296 
297 static inline bool
298 float4_le(const float4 val1, const float4 val2)
299 {
300  return isnan(val2) || (!isnan(val1) && val1 <= val2);
301 }
302 
303 static inline bool
304 float8_le(const float8 val1, const float8 val2)
305 {
306  return isnan(val2) || (!isnan(val1) && val1 <= val2);
307 }
308 
309 static inline bool
310 float4_gt(const float4 val1, const float4 val2)
311 {
312  return !isnan(val2) && (isnan(val1) || val1 > val2);
313 }
314 
315 static inline bool
316 float8_gt(const float8 val1, const float8 val2)
317 {
318  return !isnan(val2) && (isnan(val1) || val1 > val2);
319 }
320 
321 static inline bool
322 float4_ge(const float4 val1, const float4 val2)
323 {
324  return isnan(val1) || (!isnan(val2) && val1 >= val2);
325 }
326 
327 static inline bool
328 float8_ge(const float8 val1, const float8 val2)
329 {
330  return isnan(val1) || (!isnan(val2) && val1 >= val2);
331 }
332 
333 static inline float4
334 float4_min(const float4 val1, const float4 val2)
335 {
336  return float4_lt(val1, val2) ? val1 : val2;
337 }
338 
339 static inline float8
340 float8_min(const float8 val1, const float8 val2)
341 {
342  return float8_lt(val1, val2) ? val1 : val2;
343 }
344 
345 static inline float4
346 float4_max(const float4 val1, const float4 val2)
347 {
348  return float4_gt(val1, val2) ? val1 : val2;
349 }
350 
351 static inline float8
352 float8_max(const float8 val1, const float8 val2)
353 {
354  return float8_gt(val1, val2) ? val1 : val2;
355 }
356 
357 #endif /* FLOAT_H */
unsigned int uint32
Definition: c.h:490
#define PGDLLIMPORT
Definition: c.h:1303
#define pg_attribute_noreturn()
Definition: c.h:201
double float8
Definition: c.h:614
#define unlikely(x)
Definition: c.h:295
float float4
Definition: c.h:613
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:395
static float8 float8_min(const float8 val1, const float8 val2)
Definition: float.h:340
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:208
static float4 float4_div(const float4 val1, const float4 val2)
Definition: float.h:222
void float_overflow_error(void) pg_attribute_noreturn()
Definition: float.c:85
static float4 get_float4_infinity(void)
Definition: float.h:74
PGDLLIMPORT int extra_float_digits
Definition: float.c:43
static bool float4_lt(const float4 val1, const float4 val2)
Definition: float.h:286
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:158
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:182
static bool float4_ge(const float4 val1, const float4 val2)
Definition: float.h:322
static float4 get_float4_nan(void)
Definition: float.h:111
int is_infinite(float8 val)
Definition: float.c:117
void float_underflow_error(void) pg_attribute_noreturn()
Definition: float.c:93
static bool float8_ne(const float8 val1, const float8 val2)
Definition: float.h:280
static bool float4_ne(const float4 val1, const float4 val2)
Definition: float.h:274
static float4 float4_pl(const float4 val1, const float4 val2)
Definition: float.h:146
static float4 float4_max(const float4 val1, const float4 val2)
Definition: float.h:346
static bool float4_eq(const float4 val1, const float4 val2)
Definition: float.h:262
void float_zero_divide_error(void) pg_attribute_noreturn()
Definition: float.c:101
static float4 float4_mul(const float4 val1, const float4 val2)
Definition: float.h:194
static float8 get_float8_infinity(void)
Definition: float.h:94
static bool float8_ge(const float8 val1, const float8 val2)
Definition: float.h:328
int float4_cmp_internal(float4 a, float4 b)
Definition: float.c:816
float4 float4in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:182
static float4 float4_mi(const float4 val1, const float4 val2)
Definition: float.h:170
static float8 float8_max(const float8 val1, const float8 val2)
Definition: float.h:352
static bool float8_le(const float8 val1, const float8 val2)
Definition: float.h:304
static bool float4_gt(const float4 val1, const float4 val2)
Definition: float.h:310
static bool float8_eq(const float8 val1, const float8 val2)
Definition: float.h:268
static float4 float4_min(const float4 val1, const float4 val2)
Definition: float.h:334
static bool float4_le(const float4 val1, const float4 val2)
Definition: float.h:298
static float8 get_float8_nan(void)
Definition: float.h:123
static float8 float8_div(const float8 val1, const float8 val2)
Definition: float.h:238
static bool float8_lt(const float8 val1, const float8 val2)
Definition: float.h:292
static bool float8_gt(const float8 val1, const float8 val2)
Definition: float.h:316
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:910
char * float8out_internal(float8 num)
Definition: float.c:537
long val
Definition: informix.c:664
int b
Definition: isn.c:70
int a
Definition: isn.c:69
Definition: nodes.h:129