From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 30 Jul 2003 19:48:41 +0000 (+0000)
Subject: Fix numeric_smaller, numeric_larger, float4smaller, float4larger,
X-Git-Tag: REL7_4_BETA1~81
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4b1c6695f1dc55301ba17414cc0d00b85e17f7cc;p=postgresql

Fix numeric_smaller, numeric_larger, float4smaller, float4larger,
float8smaller, float8larger (and thereby the MIN/MAX aggregates on these
datatypes) to agree with the datatypes' comparison operations as
regards NaN handling.  In all these datatypes, NaN is arbitrarily
considered larger than any normal value ... but MIN/MAX had not gotten
the word.  Per recent discussion on pgsql-sql.
---

diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index ac3fb2d149..9ef2e80da7 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.90 2003/07/27 04:53:05 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.91 2003/07/30 19:48:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -109,6 +109,8 @@ int		extra_float_digits = 0;	/* Added to DBL_DIG or FLT_DIG */
 
 static void CheckFloat4Val(double val);
 static void CheckFloat8Val(double val);
+static int float4_cmp_internal(float4 a, float4 b);
+static int float8_cmp_internal(float8 a, float8 b);
 
 
 /*
@@ -413,7 +415,10 @@ float4larger(PG_FUNCTION_ARGS)
 	float4		arg2 = PG_GETARG_FLOAT4(1);
 	float4		result;
 
-	result = ((arg1 > arg2) ? arg1 : arg2);
+	if (float4_cmp_internal(arg1, arg2) > 0)
+		result = arg1;
+	else
+		result = arg2;
 	PG_RETURN_FLOAT4(result);
 }
 
@@ -424,7 +429,10 @@ float4smaller(PG_FUNCTION_ARGS)
 	float4		arg2 = PG_GETARG_FLOAT4(1);
 	float4		result;
 
-	result = ((arg1 < arg2) ? arg1 : arg2);
+	if (float4_cmp_internal(arg1, arg2) < 0)
+		result = arg1;
+	else
+		result = arg2;
 	PG_RETURN_FLOAT4(result);
 }
 
@@ -480,8 +488,10 @@ float8larger(PG_FUNCTION_ARGS)
 	float8		arg2 = PG_GETARG_FLOAT8(1);
 	float8		result;
 
-	result = ((arg1 > arg2) ? arg1 : arg2);
-
+	if (float8_cmp_internal(arg1, arg2) > 0)
+		result = arg1;
+	else
+		result = arg2;
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -492,8 +502,10 @@ float8smaller(PG_FUNCTION_ARGS)
 	float8		arg2 = PG_GETARG_FLOAT8(1);
 	float8		result;
 
-	result = ((arg1 < arg2) ? arg1 : arg2);
-
+	if (float8_cmp_internal(arg1, arg2) < 0)
+		result = arg1;
+	else
+		result = arg2;
 	PG_RETURN_FLOAT8(result);
 }
 
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 476d3d5b5c..4f5029a26c 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
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.63 2003/07/27 04:53:07 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.64 2003/07/30 19:48:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -316,7 +316,7 @@ numeric_in(PG_FUNCTION_ARGS)
 	/*
 	 * Check for NaN
 	 */
-	if (strcmp(str, "NaN") == 0)
+	if (strcasecmp(str, "NaN") == 0)
 		PG_RETURN_NUMERIC(make_result(&const_nan));
 
 	/*
@@ -1239,34 +1239,15 @@ numeric_smaller(PG_FUNCTION_ARGS)
 {
 	Numeric		num1 = PG_GETARG_NUMERIC(0);
 	Numeric		num2 = PG_GETARG_NUMERIC(1);
-	NumericVar	arg1;
-	NumericVar	arg2;
-	Numeric		res;
-
-	/*
-	 * Handle NaN
-	 */
-	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
 
 	/*
-	 * Unpack the values, and decide which is the smaller one
+	 * Use cmp_numerics so that this will agree with the comparison
+	 * operators, particularly as regards comparisons involving NaN.
 	 */
-	init_var(&arg1);
-	init_var(&arg2);
-
-	set_var_from_num(num1, &arg1);
-	set_var_from_num(num2, &arg2);
-
-	if (cmp_var(&arg1, &arg2) <= 0)
-		res = make_result(&arg1);
+	if (cmp_numerics(num1, num2) < 0)
+		PG_RETURN_NUMERIC(num1);
 	else
-		res = make_result(&arg2);
-
-	free_var(&arg1);
-	free_var(&arg2);
-
-	PG_RETURN_NUMERIC(res);
+		PG_RETURN_NUMERIC(num2);
 }
 
 
@@ -1280,34 +1261,15 @@ numeric_larger(PG_FUNCTION_ARGS)
 {
 	Numeric		num1 = PG_GETARG_NUMERIC(0);
 	Numeric		num2 = PG_GETARG_NUMERIC(1);
-	NumericVar	arg1;
-	NumericVar	arg2;
-	Numeric		res;
-
-	/*
-	 * Handle NaN
-	 */
-	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
 
 	/*
-	 * Unpack the values, and decide which is the larger one
+	 * Use cmp_numerics so that this will agree with the comparison
+	 * operators, particularly as regards comparisons involving NaN.
 	 */
-	init_var(&arg1);
-	init_var(&arg2);
-
-	set_var_from_num(num1, &arg1);
-	set_var_from_num(num2, &arg2);
-
-	if (cmp_var(&arg1, &arg2) >= 0)
-		res = make_result(&arg1);
+	if (cmp_numerics(num1, num2) > 0)
+		PG_RETURN_NUMERIC(num1);
 	else
-		res = make_result(&arg2);
-
-	free_var(&arg1);
-	free_var(&arg2);
-
-	PG_RETURN_NUMERIC(res);
+		PG_RETURN_NUMERIC(num2);
 }