codekingpro/portable-devtools
116k
1/*-------------------------------------------------------------------------2 *3 * float.h4 * Definitions for the built-in floating-point types5 *6 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group7 * Portions Copyright (c) 1994, Regents of the University of California8 *9 *10 * IDENTIFICATION11 * src/include/utils/float.h12 *13 *-------------------------------------------------------------------------14 */15#ifndef FLOAT_H16#define FLOAT_H17 18#include <math.h>19 20/* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */21#ifndef M_PI22#define M_PI 3.1415926535897932384623#endif24 25/* Radians per degree, a.k.a. PI / 180 */26#define RADIANS_PER_DEGREE 0.017453292519943295769227 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#endif34 35extern PGDLLIMPORT int extra_float_digits;36 37/*38 * Utility functions in float.c39 */40extern void float_overflow_error(void) pg_attribute_noreturn();41extern void float_underflow_error(void) pg_attribute_noreturn();42extern void float_zero_divide_error(void) pg_attribute_noreturn();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);51extern int float4_cmp_internal(float4 a, float4 b);52extern int float8_cmp_internal(float8 a, float8 b);53 54/*55 * Routines to provide reasonably platform-independent handling of56 * infinity and NaN57 *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. We62 * centralize our workarounds for this here.63 */64 65/*66 * The funny placements of the two #pragmas is necessary because of a67 * long lived bug in the Microsoft compilers.68 * See http://support.microsoft.com/kb/120968/en-us for details69 */70#ifdef _MSC_VER71#pragma warning(disable:4756)72#endif73static inline float474get_float4_infinity(void)75{76#ifdef INFINITY77 /* C99 standard way */78 return (float4) INFINITY;79#else80#ifdef _MSC_VER81#pragma warning(default:4756)82#endif83 84 /*85 * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the86 * largest normal float8. We assume forcing an overflow will get us a87 * true infinity.88 */89 return (float4) (HUGE_VAL * HUGE_VAL);90#endif91}92 93static inline float894get_float8_infinity(void)95{96#ifdef INFINITY97 /* C99 standard way */98 return (float8) INFINITY;99#else100 101 /*102 * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the103 * largest normal float8. We assume forcing an overflow will get us a104 * true infinity.105 */106 return (float8) (HUGE_VAL * HUGE_VAL);107#endif108}109 110static inline float4111get_float4_nan(void)112{113#ifdef NAN114 /* C99 standard way */115 return (float4) NAN;116#else117 /* Assume we can get a NAN via zero divide */118 return (float4) (0.0 / 0.0);119#endif120}121 122static inline float8123get_float8_nan(void)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#else130 /* Assume we can get a NaN via zero divide */131 return (float8) (0.0 / 0.0);132#endif133}134 135/*136 * Floating-point arithmetic with overflow/underflow reported as errors137 *138 * There isn't any way to check for underflow of addition/subtraction139 * because numbers near the underflow value have already been rounded to140 * the point where we can't detect that the two values were originally141 * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==142 * 1.4013e-45.143 */144 145static inline float4146float4_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))152 float_overflow_error();153 154 return result;155}156 157static inline float8158float8_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))164 float_overflow_error();165 166 return result;167}168 169static inline float4170float4_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))176 float_overflow_error();177 178 return result;179}180 181static inline float8182float8_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))188 float_overflow_error();189 190 return result;191}192 193static inline float4194float4_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))200 float_overflow_error();201 if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)202 float_underflow_error();203 204 return result;205}206 207static inline float8208float8_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))214 float_overflow_error();215 if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)216 float_underflow_error();217 218 return result;219}220 221static inline float4222float4_div(const float4 val1, const float4 val2)223{224 float4 result;225 226 if (unlikely(val2 == 0.0f) && !isnan(val1))227 float_zero_divide_error();228 result = val1 / val2;229 if (unlikely(isinf(result)) && !isinf(val1))230 float_overflow_error();231 if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))232 float_underflow_error();233 234 return result;235}236 237static inline float8238float8_div(const float8 val1, const float8 val2)239{240 float8 result;241 242 if (unlikely(val2 == 0.0) && !isnan(val1))243 float_zero_divide_error();244 result = val1 / val2;245 if (unlikely(isinf(result)) && !isinf(val1))246 float_overflow_error();247 if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))248 float_underflow_error();249 250 return result;251}252 253/*254 * Routines for NaN-aware comparisons255 *256 * We consider all NaNs to be equal and larger than any non-NaN. This is257 * somewhat arbitrary; the important thing is to have a consistent sort258 * order.259 */260 261static inline bool262float4_eq(const float4 val1, const float4 val2)263{264 return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;265}266 267static inline bool268float8_eq(const float8 val1, const float8 val2)269{270 return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;271}272 273static inline bool274float4_ne(const float4 val1, const float4 val2)275{276 return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;277}278 279static inline bool280float8_ne(const float8 val1, const float8 val2)281{282 return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;283}284 285static inline bool286float4_lt(const float4 val1, const float4 val2)287{288 return !isnan(val1) && (isnan(val2) || val1 < val2);289}290 291static inline bool292float8_lt(const float8 val1, const float8 val2)293{294 return !isnan(val1) && (isnan(val2) || val1 < val2);295}296 297static inline bool298float4_le(const float4 val1, const float4 val2)299{300 return isnan(val2) || (!isnan(val1) && val1 <= val2);301}302 303static inline bool304float8_le(const float8 val1, const float8 val2)305{306 return isnan(val2) || (!isnan(val1) && val1 <= val2);307}308 309static inline bool310float4_gt(const float4 val1, const float4 val2)311{312 return !isnan(val2) && (isnan(val1) || val1 > val2);313}314 315static inline bool316float8_gt(const float8 val1, const float8 val2)317{318 return !isnan(val2) && (isnan(val1) || val1 > val2);319}320 321static inline bool322float4_ge(const float4 val1, const float4 val2)323{324 return isnan(val1) || (!isnan(val2) && val1 >= val2);325}326 327static inline bool328float8_ge(const float8 val1, const float8 val2)329{330 return isnan(val1) || (!isnan(val2) && val1 >= val2);331}332 333static inline float4334float4_min(const float4 val1, const float4 val2)335{336 return float4_lt(val1, val2) ? val1 : val2;337}338 339static inline float8340float8_min(const float8 val1, const float8 val2)341{342 return float8_lt(val1, val2) ? val1 : val2;343}344 345static inline float4346float4_max(const float4 val1, const float4 val2)347{348 return float4_gt(val1, val2) ? val1 : val2;349}350 351static inline float8352float8_max(const float8 val1, const float8 val2)353{354 return float8_gt(val1, val2) ? val1 : val2;355}356 357#endif /* FLOAT_H */358 