1/*-------------------------------------------------------------------------
4 * Definitions for the built-in floating-point types
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/include/utils/float.h
13 *-------------------------------------------------------------------------
20/* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
22 #define M_PI 3.14159265358979323846
25/* Radians per degree, a.k.a. PI / 180 */
26 #define RADIANS_PER_DEGREE 0.0174532925199432957692
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};
32#define NAN (*(const float8 *) nan)
38 * Utility functions in float.c
45 const char *type_name,
const char *orig_string,
46 struct Node *escontext);
48 const char *type_name,
const char *orig_string,
49 struct Node *escontext);
55 * Routines to provide reasonably platform-independent handling of
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.
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
71#pragma warning(disable:4756)
77 /* C99 standard way */
81#pragma warning(default:4756)
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
89 return (
float4) (HUGE_VAL * HUGE_VAL);
97 /* C99 standard way */
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
106 return (
float8) (HUGE_VAL * HUGE_VAL);
114 /* C99 standard way */
117 /* Assume we can get a NAN via zero divide */
118 return (
float4) (0.0 / 0.0);
125 /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
126#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
127 /* C99 standard way */
130 /* Assume we can get a NaN via zero divide */
131 return (
float8) (0.0 / 0.0);
136 * Floating-point arithmetic with overflow/underflow reported as errors
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 ==
150 result = val1 + val2;
151 if (
unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
162 result = val1 + val2;
163 if (
unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
174 result = val1 - val2;
175 if (
unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
186 result = val1 - val2;
187 if (
unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
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)
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)
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))
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))
254 * Routines for NaN-aware comparisons
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
264 return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
270 return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
276 return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
282 return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
288 return !isnan(val1) && (isnan(val2) || val1 < val2);
294 return !isnan(val1) && (isnan(val2) || val1 < val2);
300 return isnan(val2) || (!isnan(val1) && val1 <= val2);
306 return isnan(val2) || (!isnan(val1) && val1 <= val2);
312 return !isnan(val2) && (isnan(val1) || val1 > val2);
318 return !isnan(val2) && (isnan(val1) || val1 > val2);
324 return isnan(val1) || (!isnan(val2) && val1 >= val2);
330 return isnan(val1) || (!isnan(val2) && val1 >= val2);
336 return float4_lt(val1, val2) ? val1 : val2;
342 return float8_lt(val1, val2) ? val1 : val2;
348 return float4_gt(val1, val2) ? val1 : val2;
354 return float8_gt(val1, val2) ? val1 : val2;
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
static float8 float8_min(const float8 val1, const float8 val2)
static float8 float8_mul(const float8 val1, const float8 val2)
static float4 float4_div(const float4 val1, const float4 val2)
static float4 get_float4_infinity(void)
pg_noreturn void float_overflow_error(void)
PGDLLIMPORT int extra_float_digits
static bool float4_lt(const float4 val1, const float4 val2)
static float8 float8_pl(const float8 val1, const float8 val2)
static float8 float8_mi(const float8 val1, const float8 val2)
static bool float4_ge(const float4 val1, const float4 val2)
static float4 get_float4_nan(void)
int is_infinite(float8 val)
static bool float8_ne(const float8 val1, const float8 val2)
static bool float4_ne(const float4 val1, const float4 val2)
static float4 float4_pl(const float4 val1, const float4 val2)
static float4 float4_max(const float4 val1, const float4 val2)
static bool float4_eq(const float4 val1, const float4 val2)
static float4 float4_mul(const float4 val1, const float4 val2)
pg_noreturn void float_underflow_error(void)
static float8 get_float8_infinity(void)
static bool float8_ge(const float8 val1, const float8 val2)
int float4_cmp_internal(float4 a, float4 b)
char * float8out_internal(float8 num)
float4 float4in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
static float4 float4_mi(const float4 val1, const float4 val2)
static float8 float8_max(const float8 val1, const float8 val2)
static bool float8_le(const float8 val1, const float8 val2)
static bool float4_gt(const float4 val1, const float4 val2)
static bool float8_eq(const float8 val1, const float8 val2)
static float4 float4_min(const float4 val1, const float4 val2)
static bool float4_le(const float4 val1, const float4 val2)
static float8 get_float8_nan(void)
static float8 float8_div(const float8 val1, const float8 val2)
pg_noreturn void float_zero_divide_error(void)
static bool float8_lt(const float8 val1, const float8 val2)
static bool float8_gt(const float8 val1, const float8 val2)
int float8_cmp_internal(float8 a, float8 b)