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-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 
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
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
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
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
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 */
static bool float8_ne(const float8 val1, const float8 val2)
Definition: float.h:302
PGDLLIMPORT int extra_float_digits
Definition: float.c:42
static float4 float4_div(const float4 val1, const float4 val2)
Definition: float.h:244
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:919
static float8 get_float8_infinity(void)
Definition: float.h:90
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string)
Definition: float.c:518
static float8 float8_min(const float8 val1, const float8 val2)
Definition: float.h:362
static bool float8_le(const float8 val1, const float8 val2)
Definition: float.h:326
int errcode(int sqlerrcode)
Definition: elog.c:570
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:232
#define PGDLLIMPORT
Definition: c.h:1243
static void check_float8_val(const float8 val, const bool inf_is_valid, const bool zero_is_valid)
Definition: float.h:151
static float4 float4_mi(const float4 val1, const float4 val2)
Definition: float.h:198
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:491
static void check_float4_val(const float4 val, const bool inf_is_valid, const bool zero_is_valid)
Definition: float.h:136
static float8 get_float8_nan(void)
Definition: float.h:119
int isinf(double x)
int is_infinite(float8 val)
Definition: float.c:97
static bool float8_ge(const float8 val1, const float8 val2)
Definition: float.h:350
unsigned int uint32
Definition: c.h:358
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:187
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:209
static float4 float4_min(const float4 val1, const float4 val2)
Definition: float.h:356
char * float8out_internal(float8 num)
Definition: float.c:546
static bool float4_gt(const float4 val1, const float4 val2)
Definition: float.h:332
#define ereport(elevel, rest)
Definition: elog.h:141
static bool float8_lt(const float8 val1, const float8 val2)
Definition: float.h:314
static float4 get_float4_nan(void)
Definition: float.h:107
float8 float8in_internal_opt_error(char *num, char **endptr_p, const char *type_name, const char *orig_string, bool *have_error)
Definition: float.c:372
float float4
Definition: c.h:490
static bool float4_lt(const float4 val1, const float4 val2)
Definition: float.h:308
static bool float8_gt(const float8 val1, const float8 val2)
Definition: float.h:338
static bool float4_ge(const float4 val1, const float4 val2)
Definition: float.h:344
static bool float4_ne(const float4 val1, const float4 val2)
Definition: float.h:296
int float4_cmp_internal(float4 a, float4 b)
Definition: float.c:825
static float8 float8_div(const float8 val1, const float8 val2)
Definition: float.h:260
static bool float4_eq(const float4 val1, const float4 val2)
Definition: float.h:284
static bool float8_eq(const float8 val1, const float8 val2)
Definition: float.h:290
int errmsg(const char *fmt,...)
Definition: elog.c:784
static bool float4_le(const float4 val1, const float4 val2)
Definition: float.h:320
static float4 float4_pl(const float4 val1, const float4 val2)
Definition: float.h:176
static float4 float4_mul(const float4 val1, const float4 val2)
Definition: float.h:220
#define unlikely(x)
Definition: c.h:208
static float8 float8_max(const float8 val1, const float8 val2)
Definition: float.h:374
long val
Definition: informix.c:684
static float4 float4_max(const float4 val1, const float4 val2)
Definition: float.h:368
static float4 get_float4_infinity(void)
Definition: float.h:70