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-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/* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
29#if defined(WIN32) && !defined(NAN)
30static 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 */
40pg_noreturn extern void float_overflow_error(void);
41pg_noreturn extern void float_underflow_error(void);
42pg_noreturn extern void float_zero_divide_error(void);
43extern int is_infinite(float8 val);
44extern float8 float8in_internal(char *num, char **endptr_p,
45 const char *type_name, const char *orig_string,
46 struct Node *escontext);
47extern float4 float4in_internal(char *num, char **endptr_p,
48 const char *type_name, const char *orig_string,
49 struct Node *escontext);
50extern char *float8out_internal(float8 num);
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
73static 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
93static 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
110static 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
122static 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
145static inline float4
146float4_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
157static inline float8
158float8_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
169static inline float4
170float4_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
181static inline float8
182float8_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
193static inline float4
194float4_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
207static inline float8
208float8_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
221static inline float4
222float4_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
237static inline float8
238float8_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
261static inline bool
262float4_eq(const float4 val1, const float4 val2)
263{
264 return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
265}
266
267static inline bool
268float8_eq(const float8 val1, const float8 val2)
269{
270 return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
271}
272
273static inline bool
274float4_ne(const float4 val1, const float4 val2)
275{
276 return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
277}
278
279static inline bool
280float8_ne(const float8 val1, const float8 val2)
281{
282 return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
283}
284
285static inline bool
286float4_lt(const float4 val1, const float4 val2)
287{
288 return !isnan(val1) && (isnan(val2) || val1 < val2);
289}
290
291static inline bool
292float8_lt(const float8 val1, const float8 val2)
293{
294 return !isnan(val1) && (isnan(val2) || val1 < val2);
295}
296
297static inline bool
298float4_le(const float4 val1, const float4 val2)
299{
300 return isnan(val2) || (!isnan(val1) && val1 <= val2);
301}
302
303static inline bool
304float8_le(const float8 val1, const float8 val2)
305{
306 return isnan(val2) || (!isnan(val1) && val1 <= val2);
307}
308
309static inline bool
310float4_gt(const float4 val1, const float4 val2)
311{
312 return !isnan(val2) && (isnan(val1) || val1 > val2);
313}
314
315static inline bool
316float8_gt(const float8 val1, const float8 val2)
317{
318 return !isnan(val2) && (isnan(val1) || val1 > val2);
319}
320
321static inline bool
322float4_ge(const float4 val1, const float4 val2)
323{
324 return isnan(val1) || (!isnan(val2) && val1 >= val2);
325}
326
327static inline bool
328float8_ge(const float8 val1, const float8 val2)
329{
330 return isnan(val1) || (!isnan(val2) && val1 >= val2);
331}
332
333static inline float4
334float4_min(const float4 val1, const float4 val2)
335{
336 return float4_lt(val1, val2) ? val1 : val2;
337}
338
339static inline float8
340float8_min(const float8 val1, const float8 val2)
341{
342 return float8_lt(val1, val2) ? val1 : val2;
343}
344
345static inline float4
346float4_max(const float4 val1, const float4 val2)
347{
348 return float4_gt(val1, val2) ? val1 : val2;
349}
350
351static inline float8
352float8_max(const float8 val1, const float8 val2)
353{
354 return float8_gt(val1, val2) ? val1 : val2;
355}
356
357#endif /* FLOAT_H */
#define PGDLLIMPORT
Definition: c.h:1291
#define pg_noreturn
Definition: c.h:165
double float8
Definition: c.h:601
#define unlikely(x)
Definition: c.h:347
uint32_t uint32
Definition: c.h:502
float float4
Definition: c.h:600
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
static float4 get_float4_infinity(void)
Definition: float.h:74
pg_noreturn void float_overflow_error(void)
Definition: float.c:86
PGDLLIMPORT int extra_float_digits
Definition: float.c:40
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:118
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
static float4 float4_mul(const float4 val1, const float4 val2)
Definition: float.h:194
pg_noreturn void float_underflow_error(void)
Definition: float.c:94
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
char * float8out_internal(float8 num)
Definition: float.c:537
float4 float4in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:183
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
pg_noreturn void float_zero_divide_error(void)
Definition: float.c:102
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
long val
Definition: informix.c:689
int b
Definition: isn.c:71
int a
Definition: isn.c:70
Definition: nodes.h:131