From 14ad0d7bf2b8d5f26061df7cbdf18cfffcdcb225 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 8 Oct 2025 12:19:53 -0400 Subject: [PATCH] Cleanup NAN code in float.h, too. In the same spirit as 3bf905692, assume that all compilers we still support provide the NAN macro, and get rid of workarounds for that. The C standard allows implementations to omit NAN if the underlying float arithmetic lacks quiet (non-signaling) NaNs. However, we've required that feature for years: the workarounds only supported lack of the macro, not lack of the functionality. I put in a compile-time #error if there's no macro, just for clarity. Also fix up the copies of these functions in ecpglib, and leave a breadcrumb for the next hacker who touches them. History of the hacks being removed here can be found in commits 1bc2d544b, 4d17a2146, cec8394b5. Author: Tom Lane Discussion: https://postgr.es/m/1952095.1759764279@sss.pgh.pa.us --- src/include/utils/float.h | 40 +++++++++++------------------- src/interfaces/ecpg/ecpglib/data.c | 19 +++----------- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/src/include/utils/float.h b/src/include/utils/float.h index fa903b4bf59..fc2a9cf6475 100644 --- a/src/include/utils/float.h +++ b/src/include/utils/float.h @@ -25,13 +25,6 @@ /* Radians per degree, a.k.a. PI / 180 */ #define RADIANS_PER_DEGREE 0.0174532925199432957692 -/* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */ -#if defined(WIN32) && !defined(NAN) -static const uint32 nan[2] = {0xffffffff, 0x7fffffff}; - -#define NAN (*(const float8 *) nan) -#endif - extern PGDLLIMPORT int extra_float_digits; /* @@ -51,6 +44,16 @@ extern char *float8out_internal(float8 num); extern int float4_cmp_internal(float4 a, float4 b); extern int float8_cmp_internal(float8 a, float8 b); +/* + * Postgres requires IEEE-standard float arithmetic, including infinities + * and NaNs. We used to support pre-C99 compilers on which might + * not supply the standard macros INFINITY and NAN. We no longer do so, + * but these wrapper functions are still preferred over using those macros + * directly. + * + * If you change these functions, see copies in interfaces/ecpg/ecpglib/data.c. + */ + static inline float4 get_float4_infinity(void) { @@ -65,36 +68,23 @@ get_float8_infinity(void) return (float8) INFINITY; } -/* - * Routines to provide reasonably platform-independent handling of NaN - * - * We assume that isnan() is available and work per spec. However, generating - * a NaN in the first place is less well standardized; pre-C99 systems tend - * not to have C99's NaN macro. We centralize our workaround for this here. - */ +/* The C standard allows implementations to omit NAN, but we don't */ +#ifndef NAN +#error "Postgres requires support for IEEE quiet NaNs" +#endif + static inline float4 get_float4_nan(void) { -#ifdef NAN /* C99 standard way */ return (float4) NAN; -#else - /* Assume we can get a NAN via zero divide */ - return (float4) (0.0 / 0.0); -#endif } static inline float8 get_float8_nan(void) { - /* (float8) NAN doesn't work on some NetBSD/MIPS releases */ -#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__)) /* C99 standard way */ return (float8) NAN; -#else - /* Assume we can get a NaN via zero divide */ - return (float8) (0.0 / 0.0); -#endif } /* diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index fa562767585..d5d40f7b654 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -69,34 +69,23 @@ garbage_left(enum ARRAY_TYPE isarray, char **scan_length, enum COMPAT_MODE compa return false; } -/* stolen code from src/backend/utils/adt/float.c */ -#if defined(WIN32) && !defined(NAN) -static const uint32 nan[2] = {0xffffffff, 0x7fffffff}; - -#define NAN (*(const double *) nan) -#endif +/* + * Portability wrappers borrowed from src/include/utils/float.h + */ static double get_float8_infinity(void) { -#ifdef INFINITY return (double) INFINITY; -#else - return (double) (HUGE_VAL * HUGE_VAL); -#endif } static double get_float8_nan(void) { - /* (double) NAN doesn't work on some NetBSD/MIPS releases */ -#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__)) return (double) NAN; -#else - return (double) (0.0 / 0.0); -#endif } + static bool check_special_value(char *ptr, double *retval, char **endptr) { -- 2.47.3