From 1bc2d544b979164a276f9e6052f0b6d23af59b60 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 15 Mar 2004 03:29:22 +0000 Subject: [PATCH] Localize our dependencies on the way to create NAN or INFINITY. Per recent proposal to pghackers. --- contrib/seg/seg.c | 4 +- contrib/seg/segparse.y | 8 +-- src/backend/port/qnx4/isnan.c | 12 +++- src/backend/utils/adt/float.c | 99 +++++++++++++++++++++++++------ src/backend/utils/adt/numeric.c | 17 ++---- src/backend/utils/adt/timestamp.c | 6 +- src/include/port/qnx4.h | 10 ---- src/include/port/solaris.h | 23 +------ src/include/utils/builtins.h | 8 ++- 9 files changed, 106 insertions(+), 81 deletions(-) diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c index c26f9d27cd..b04441b1ed 100644 --- a/contrib/seg/seg.c +++ b/contrib/seg/seg.c @@ -755,7 +755,7 @@ seg_cmp(SEG * a, SEG * b) * a->lower == b->lower, so consider type of boundary. * * A '-' lower bound is < any other kind (this could only be relevant if - * -HUGE is used as a regular data value). A '<' lower bound is < any + * -HUGE_VAL is used as a regular data value). A '<' lower bound is < any * other kind except '-'. A '>' lower bound is > any other kind. */ if (a->l_ext != b->l_ext) @@ -813,7 +813,7 @@ seg_cmp(SEG * a, SEG * b) * a->upper == b->upper, so consider type of boundary. * * A '-' upper bound is > any other kind (this could only be relevant if - * HUGE is used as a regular data value). A '<' upper bound is < any + * HUGE_VAL is used as a regular data value). A '<' upper bound is < any * other kind. A '>' upper bound is > any other kind except '-'. */ if (a->u_ext != b->u_ext) diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y index d8de412081..9ed9dcbdbd 100644 --- a/contrib/seg/segparse.y +++ b/contrib/seg/segparse.y @@ -6,10 +6,6 @@ #include #include "segdata.h" - -#ifdef __CYGWIN__ -#define HUGE HUGE_VAL -#endif /* __CYGWIN__ */ #undef yylex /* falure to redefine yylex will result in calling the */ #define yylex seg_yylex /* wrong scanner when running inside postgres backend */ @@ -86,7 +82,7 @@ range: | boundary RANGE { ((SEG *)result)->lower = $1.val; - ((SEG *)result)->upper = HUGE; + ((SEG *)result)->upper = HUGE_VAL; ((SEG *)result)->l_sigd = $1.sigd; ((SEG *)result)->u_sigd = 0; ((SEG *)result)->l_ext = ( $1.ext ? $1.ext : '\0' ); @@ -94,7 +90,7 @@ range: } | RANGE boundary { - ((SEG *)result)->lower = -HUGE; + ((SEG *)result)->lower = -HUGE_VAL; ((SEG *)result)->upper = $2.val; ((SEG *)result)->l_sigd = 0; ((SEG *)result)->u_sigd = $2.sigd; diff --git a/src/backend/port/qnx4/isnan.c b/src/backend/port/qnx4/isnan.c index 6fe3c87b30..e11147265b 100644 --- a/src/backend/port/qnx4/isnan.c +++ b/src/backend/port/qnx4/isnan.c @@ -7,17 +7,23 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/port/qnx4/isnan.c,v 1.4 2003/11/29 19:51:54 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/port/qnx4/isnan.c,v 1.5 2004/03/15 03:29:22 tgl Exp $ * *------------------------------------------------------------------------- */ #include "c.h" -unsigned char __nan[8] = __nan_bytes; +#include + +#ifndef __nan_bytes +#define __nan_bytes { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } +#endif /* __nan_bytes */ + +static unsigned char __nan[8] = __nan_bytes; int isnan(double dsrc) { - return !memcmp(&dsrc, &NAN, sizeof(double)); + return memcmp(&dsrc, __nan, sizeof(double)) == 0; } diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 9e078bfb34..bdedd83e6e 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.100 2004/03/14 05:22:52 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.101 2004/03/15 03:29:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -54,9 +54,8 @@ #include #include -#include /* faked on sunos4 */ +#include #include - #include /* for finite() on Solaris */ #ifdef HAVE_IEEEFP_H @@ -70,19 +69,11 @@ #include "utils/builtins.h" -#ifndef HAVE_CBRT -static double cbrt(double x); -#endif /* HAVE_CBRT */ - #ifndef M_PI /* from my RH5.2 gcc math.h file - thomas 2000-04-03 */ #define M_PI 3.14159265358979323846 #endif -#ifndef NAN -#define NAN (0.0/0.0) -#endif - #ifndef SHRT_MAX #define SHRT_MAX 32767 #endif @@ -109,9 +100,78 @@ int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */ static void CheckFloat4Val(double val); static void CheckFloat8Val(double val); -static int is_infinite(double val); static int float4_cmp_internal(float4 a, float4 b); static int float8_cmp_internal(float8 a, float8 b); +#ifndef HAVE_CBRT +static double cbrt(double x); +#endif /* HAVE_CBRT */ + + +/* + * Routines to provide reasonably platform-independent handling of + * infinity and NaN. We assume that isinf() and isnan() are available + * and work per spec. (On some platforms, we have to supply our own; + * see src/port.) However, generating an Infinity or NaN in the first + * place is less well standardized; pre-C99 systems tend not to have C99's + * INFINITY and NAN macros. We centralize our workarounds for this here. + */ + +double +get_float8_infinity(void) +{ +#ifdef INFINITY + /* C99 standard way */ + return (double) INFINITY; +#else + /* + * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the + * largest normal double. We assume forcing an overflow will get us + * a true infinity. + */ + return (double) (HUGE_VAL * HUGE_VAL); +#endif +} + +float +get_float4_infinity(void) +{ +#ifdef INFINITY + /* C99 standard way */ + return (float) INFINITY; +#else + /* + * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the + * largest normal double. We assume forcing an overflow will get us + * a true infinity. + */ + return (float) (HUGE_VAL * HUGE_VAL); +#endif +} + +double +get_float8_nan(void) +{ +#ifdef NAN + /* C99 standard way */ + return (double) NAN; +#else + /* Assume we can get a NAN via zero divide */ + return (double) (0.0 / 0.0); +#endif +} + +float +get_float4_nan(void) +{ +#ifdef NAN + /* C99 standard way */ + return (float) NAN; +#else + /* Assume we can get a NAN via zero divide */ + return (float) (0.0 / 0.0); +#endif +} + /* * Returns -1 if 'val' represents negative infinity, 1 if 'val' @@ -120,7 +180,7 @@ static int float8_cmp_internal(float8 a, float8 b); * does not specify that isinf() needs to distinguish between positive * and negative infinity. */ -static int +int is_infinite(double val) { int inf = isinf(val); @@ -134,6 +194,7 @@ is_infinite(double val) return -1; } + /* * check to see if a float4 val is outside of the FLOAT4_MIN, * FLOAT4_MAX bounds. @@ -237,17 +298,17 @@ float4in(PG_FUNCTION_ARGS) */ if (strncasecmp(num, "NaN", 3) == 0) { - val = NAN; + val = get_float4_nan(); endptr = num + 3; } else if (strncasecmp(num, "Infinity", 8) == 0) { - val = HUGE_VAL; + val = get_float4_infinity(); endptr = num + 8; } else if (strncasecmp(num, "-Infinity", 9) == 0) { - val = -HUGE_VAL; + val = - get_float4_infinity(); endptr = num + 9; } else @@ -402,17 +463,17 @@ float8in(PG_FUNCTION_ARGS) */ if (strncasecmp(num, "NaN", 3) == 0) { - val = NAN; + val = get_float8_nan(); endptr = num + 3; } else if (strncasecmp(num, "Infinity", 8) == 0) { - val = HUGE_VAL; + val = get_float8_infinity(); endptr = num + 8; } else if (strncasecmp(num, "-Infinity", 9) == 0) { - val = -HUGE_VAL; + val = - get_float8_infinity(); endptr = num + 9; } else diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index f093c414ee..341bd9cc4c 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -14,7 +14,7 @@ * Copyright (c) 1998-2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.71 2004/02/04 01:11:47 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.72 2004/03/15 03:29:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,15 +42,6 @@ */ -/* ---------- - * Local definitions - * ---------- - */ -#ifndef NAN -#define NAN (0.0/0.0) -#endif - - /* ---------- * Local data types * @@ -1790,7 +1781,7 @@ numeric_float8(PG_FUNCTION_ARGS) Datum result; if (NUMERIC_IS_NAN(num)) - PG_RETURN_FLOAT8(NAN); + PG_RETURN_FLOAT8(get_float8_nan()); tmp = DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(num))); @@ -1811,7 +1802,7 @@ numeric_float8_no_overflow(PG_FUNCTION_ARGS) double val; if (NUMERIC_IS_NAN(num)) - PG_RETURN_FLOAT8(NAN); + PG_RETURN_FLOAT8(get_float8_nan()); val = numeric_to_double_no_overflow(num); @@ -1850,7 +1841,7 @@ numeric_float4(PG_FUNCTION_ARGS) Datum result; if (NUMERIC_IS_NAN(num)) - PG_RETURN_FLOAT4((float4) NAN); + PG_RETURN_FLOAT4(get_float4_nan()); tmp = DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(num))); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 4fb5f743b0..582bc369d5 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.100 2004/03/05 02:41:14 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.101 2004/03/15 03:29:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,10 +20,6 @@ #include #include #include -/* for finite() on Solaris */ -#ifdef HAVE_IEEEFP_H -#include -#endif #include "access/hash.h" #include "access/xact.h" diff --git a/src/include/port/qnx4.h b/src/include/port/qnx4.h index 585bee010c..68deca4a1c 100644 --- a/src/include/port/qnx4.h +++ b/src/include/port/qnx4.h @@ -9,18 +9,8 @@ #define strncasecmp strnicmp -#ifndef NAN -#ifndef __nan_bytes -#define __nan_bytes { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } -#endif /* __nan_bytes */ -extern unsigned char __nan[8]; - -#define NAN (*(const double *) __nan) -#endif /* NAN */ - typedef u_short ushort; extern int isnan(double dsrc); - extern long random(void); extern void srandom(unsigned int seed); diff --git a/src/include/port/solaris.h b/src/include/port/solaris.h index 8476fe362c..f37e2a2a88 100644 --- a/src/include/port/solaris.h +++ b/src/include/port/solaris.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/include/port/solaris.h,v 1.10 2003/12/23 03:31:30 momjian Exp $ */ +/* $PostgreSQL: pgsql/src/include/port/solaris.h,v 1.11 2004/03/15 03:29:22 tgl Exp $ */ /* * Sort this out for all operating systems some time. The __xxx @@ -35,24 +35,3 @@ #define BYTE_ORDER LITTLE_ENDIAN #endif #endif - - -#ifndef NAN - -#if defined(__GNUC__) && defined(__i386__) - -#ifndef __nan_bytes -#define __nan_bytes { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } -#endif - -#define NAN \ - (__extension__ ((union { unsigned char __c[8]; double __d; }) \ - { __nan_bytes }).__d) - -#else -/* not GNUC and i386 */ - -#define NAN (0.0/0.0) -#endif /* GCC. */ - -#endif /* not NAN */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 593f002c68..b7c1f5fea7 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.234 2004/02/03 08:29:57 joe Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.235 2004/03/15 03:29:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -240,6 +240,12 @@ extern Datum bttext_pattern_cmp(PG_FUNCTION_ARGS); /* float.c */ extern DLLIMPORT int extra_float_digits; +extern double get_float8_infinity(void); +extern float get_float4_infinity(void); +extern double get_float8_nan(void); +extern float get_float4_nan(void); +extern int is_infinite(double val); + extern Datum float4in(PG_FUNCTION_ARGS); extern Datum float4out(PG_FUNCTION_ARGS); extern Datum float4recv(PG_FUNCTION_ARGS);