From 1bc2d544b979164a276f9e6052f0b6d23af59b60 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
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 c26f9d27cd7..b04441b1ed2 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 d8de4120811..9ed9dcbdbd9 100644
--- a/contrib/seg/segparse.y
+++ b/contrib/seg/segparse.y
@@ -6,10 +6,6 @@
 #include <math.h>
 
 #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 6fe3c87b303..e11147265b9 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 <math.h>
+
+#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 9e078bfb349..bdedd83e6e3 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 <ctype.h>
 #include <errno.h>
-#include <float.h>				/* faked on sunos4 */
+#include <float.h>
 #include <math.h>
-
 #include <limits.h>
 /* 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 f093c414ee5..341bd9cc4c5 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 4fb5f743b03..582bc369d5d 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 <errno.h>
 #include <float.h>
 #include <limits.h>
-/* for finite() on Solaris */
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
 
 #include "access/hash.h"
 #include "access/xact.h"
diff --git a/src/include/port/qnx4.h b/src/include/port/qnx4.h
index 585bee010c3..68deca4a1c3 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 8476fe362c8..f37e2a2a88b 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 593f002c68f..b7c1f5fea77 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);
-- 
GitLab