Index: src/backend/utils/adt/float.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/float.c,v
retrieving revision 1.131
diff -c -c -r1.131 float.c
*** src/backend/utils/adt/float.c	23 Dec 2006 02:13:24 -0000	1.131
--- src/backend/utils/adt/float.c	27 Dec 2006 18:43:26 -0000
***************
*** 104,111 ****
  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);
  
--- 104,111 ----
  int			extra_float_digits = 0;		/* Added to DBL_DIG or FLT_DIG */
  
  
! static void CheckFloat4Val(double val, bool has_inf_args);
! static void CheckFloat8Val(double val, bool has_inf_args);
  static int	float4_cmp_internal(float4 a, float4 b);
  static int	float8_cmp_internal(float8 a, float8 b);
  
***************
*** 211,219 ****
   * raise an ereport() error if it is
   */
  static void
! CheckFloat4Val(double val)
  {
! 	if (fabs(val) > FLOAT4_MAX)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("type \"real\" value out of range: overflow")));
--- 211,220 ----
   * raise an ereport() error if it is
   */
  static void
! CheckFloat4Val(double val, bool has_inf_args)
  {
! 	/* If one of the input arguments was infinity, allow an infinite result */
! 	if (fabs(val) > FLOAT4_MAX && (!isinf(val) || !has_inf_args))
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("type \"real\" value out of range: overflow")));
***************
*** 230,241 ****
   * raise an ereport() error if it is
   */
  static void
! CheckFloat8Val(double val)
  {
! 	if (fabs(val) > FLOAT8_MAX)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  		  errmsg("type \"double precision\" value out of range: overflow")));
  	if (val != 0.0 && fabs(val) < FLOAT8_MIN)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
--- 231,261 ----
   * raise an ereport() error if it is
   */
  static void
! CheckFloat8Val(double val, bool has_inf_args)
  {
! 	/*
! 	 *	Computations that slightly exceed FLOAT8_MAX are non-Infinity,
! 	 *	but those that greatly exceed FLOAT8_MAX become Infinity.  Therefore
! 	 *	it is difficult to tell if a value is really infinity or the result
! 	 *	of an overflow.  The solution is to use a boolean indicating if
! 	 *	the input arguments were infiity, meaning an infinite result is
! 	 *	probably not the result of an overflow.  This allows various
! 	 *	computations like SELECT 'Inf'::float8 + 5.
! 	 */
! 	if (fabs(val) > FLOAT8_MAX && (!isinf(val) || !has_inf_args))
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  		  errmsg("type \"double precision\" value out of range: overflow")));
+ 	/*
+ 	 *	Underflow has similar issues to overflow, i.e. if a computation is
+ 	 *	slighly smaller than FLOAT8_MIN, the result is non-zero, but if it is
+ 	 *	much smaller than FLOAT8_MIN, the value becomes zero.  However,
+ 	 *	unlike overflow, zero is not a special value and can be the result
+ 	 *	of a computation, so there is no easy way to pass a boolean
+ 	 *	indicating whether a zero result is reasonable or not.  It might
+ 	 *	be possible for multiplication and division, but because of rounding,
+ 	 *	such tests would probably not be reliable.
+ 	 */
  	if (val != 0.0 && fabs(val) < FLOAT8_MIN)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
***************
*** 369,376 ****
  	 * if we get here, we have a legal double, still need to check to see if
  	 * it's a legal float4
  	 */
! 	if (!isinf(val))
! 		CheckFloat4Val(val);
  
  	PG_RETURN_FLOAT4((float4) val);
  }
--- 389,395 ----
  	 * if we get here, we have a legal double, still need to check to see if
  	 * it's a legal float4
  	 */
! 	CheckFloat4Val(val, true /* allow Inf */);
  
  	PG_RETURN_FLOAT4((float4) val);
  }
***************
*** 558,565 ****
  			 errmsg("invalid input syntax for type double precision: \"%s\"",
  					orig_num)));
  
! 	if (!isinf(val))
! 		CheckFloat8Val(val);
  
  	PG_RETURN_FLOAT8(val);
  }
--- 577,583 ----
  			 errmsg("invalid input syntax for type double precision: \"%s\"",
  					orig_num)));
  
! 	CheckFloat8Val(val, true /* allow Inf */);
  
  	PG_RETURN_FLOAT8(val);
  }
***************
*** 652,659 ****
  float4um(PG_FUNCTION_ARGS)
  {
  	float4		arg1 = PG_GETARG_FLOAT4(0);
  
! 	PG_RETURN_FLOAT4((float4) -arg1);
  }
  
  Datum
--- 670,681 ----
  float4um(PG_FUNCTION_ARGS)
  {
  	float4		arg1 = PG_GETARG_FLOAT4(0);
+ 	float4		result;
+ 
+ 	result = ((arg1 != 0) ? -(arg1) : arg1);
  
! 	CheckFloat4Val(result, isinf(arg1));
! 	PG_RETURN_FLOAT4(result);
  }
  
  Datum
***************
*** 705,716 ****
  float8abs(PG_FUNCTION_ARGS)
  {
  	float8		arg1 = PG_GETARG_FLOAT8(0);
- 	float8		result;
  
! 	result = fabs(arg1);
! 
! 	CheckFloat8Val(result);
! 	PG_RETURN_FLOAT8(result);
  }
  
  
--- 727,734 ----
  float8abs(PG_FUNCTION_ARGS)
  {
  	float8		arg1 = PG_GETARG_FLOAT8(0);
  
! 	PG_RETURN_FLOAT8(fabs(arg1));
  }
  
  
***************
*** 725,731 ****
  
  	result = ((arg1 != 0) ? -(arg1) : arg1);
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 743,749 ----
  
  	result = ((arg1 != 0) ? -(arg1) : arg1);
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 786,792 ****
  	double		result;
  
  	result = arg1 + arg2;
! 	CheckFloat4Val(result);
  	PG_RETURN_FLOAT4((float4) result);
  }
  
--- 804,810 ----
  	double		result;
  
  	result = arg1 + arg2;
! 	CheckFloat4Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT4((float4) result);
  }
  
***************
*** 798,804 ****
  	double		result;
  
  	result = arg1 - arg2;
! 	CheckFloat4Val(result);
  	PG_RETURN_FLOAT4((float4) result);
  }
  
--- 816,822 ----
  	double		result;
  
  	result = arg1 - arg2;
! 	CheckFloat4Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT4((float4) result);
  }
  
***************
*** 810,816 ****
  	double		result;
  
  	result = arg1 * arg2;
! 	CheckFloat4Val(result);
  	PG_RETURN_FLOAT4((float4) result);
  }
  
--- 828,834 ----
  	double		result;
  
  	result = arg1 * arg2;
! 	CheckFloat4Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT4((float4) result);
  }
  
***************
*** 829,835 ****
  	/* Do division in float8, then check for overflow */
  	result = (float8) arg1 / (float8) arg2;
  
! 	CheckFloat4Val(result);
  	PG_RETURN_FLOAT4((float4) result);
  }
  
--- 847,853 ----
  	/* Do division in float8, then check for overflow */
  	result = (float8) arg1 / (float8) arg2;
  
! 	CheckFloat4Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT4((float4) result);
  }
  
***************
*** 848,854 ****
  
  	result = arg1 + arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 866,872 ----
  
  	result = arg1 + arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 861,867 ****
  
  	result = arg1 - arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 879,885 ----
  
  	result = arg1 - arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 874,880 ****
  
  	result = arg1 * arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 892,898 ----
  
  	result = arg1 * arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 892,898 ****
  
  	result = arg1 / arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 910,916 ----
  
  	result = arg1 / arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1142,1148 ****
  {
  	float8		num = PG_GETARG_FLOAT8(0);
  
! 	CheckFloat4Val(num);
  
  	PG_RETURN_FLOAT4((float4) num);
  }
--- 1160,1166 ----
  {
  	float8		num = PG_GETARG_FLOAT8(0);
  
! 	CheckFloat4Val(num, isinf(num));
  
  	PG_RETURN_FLOAT4((float4) num);
  }
***************
*** 1157,1163 ****
  	float8		num = PG_GETARG_FLOAT8(0);
  	int32		result;
  
! 	if (num < INT_MIN || num > INT_MAX)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("integer out of range")));
--- 1175,1182 ----
  	float8		num = PG_GETARG_FLOAT8(0);
  	int32		result;
  
! 	/* 'Inf' is handled by INT_MAX */
! 	if (num < INT_MIN || num > INT_MAX || isnan(num))
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("integer out of range")));
***************
*** 1176,1182 ****
  	float8		num = PG_GETARG_FLOAT8(0);
  	int16		result;
  
! 	if (num < SHRT_MIN || num > SHRT_MAX)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("smallint out of range")));
--- 1195,1201 ----
  	float8		num = PG_GETARG_FLOAT8(0);
  	int16		result;
  
! 	if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("smallint out of range")));
***************
*** 1223,1229 ****
  	float4		num = PG_GETARG_FLOAT4(0);
  	int32		result;
  
! 	if (num < INT_MIN || num > INT_MAX)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("integer out of range")));
--- 1242,1248 ----
  	float4		num = PG_GETARG_FLOAT4(0);
  	int32		result;
  
! 	if (num < INT_MIN || num > INT_MAX || isnan(num))
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("integer out of range")));
***************
*** 1242,1248 ****
  	float4		num = PG_GETARG_FLOAT4(0);
  	int16		result;
  
! 	if (num < SHRT_MIN || num > SHRT_MAX)
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("smallint out of range")));
--- 1261,1267 ----
  	float4		num = PG_GETARG_FLOAT4(0);
  	int16		result;
  
! 	if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
  		ereport(ERROR,
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("smallint out of range")));
***************
*** 1485,1491 ****
  
  	result = sqrt(arg1);
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1504,1510 ----
  
  	result = sqrt(arg1);
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1500,1505 ****
--- 1519,1525 ----
  	float8		result;
  
  	result = cbrt(arg1);
+ 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1539,1545 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("result is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1559,1565 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("result is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1569,1575 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("result is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1589,1595 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("result is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1598,1604 ****
  
  	result = log(arg1);
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1618,1624 ----
  
  	result = log(arg1);
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1628,1634 ****
  
  	result = log10(arg1);
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1648,1654 ----
  
  	result = log10(arg1);
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1653,1659 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1673,1679 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1678,1684 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1698,1704 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1703,1709 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1723,1729 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1729,1735 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1749,1755 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1754,1760 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1774,1780 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1780,1786 ****
  				 errmsg("input is out of range")));
  
  	result = 1.0 / result;
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1800,1806 ----
  				 errmsg("input is out of range")));
  
  	result = 1.0 / result;
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1805,1811 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1825,1831 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1830,1836 ****
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1850,1856 ----
  				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  				 errmsg("input is out of range")));
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1846,1852 ****
  
  	result = arg1 * (180.0 / M_PI);
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1866,1872 ----
  
  	result = arg1 * (180.0 / M_PI);
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1872,1878 ****
  
  	result = arg1 * (M_PI / 180.0);
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 1892,1898 ----
  
  	result = arg1 * (M_PI / 180.0);
  
! 	CheckFloat8Val(result, isinf(arg1));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 1963,1970 ****
  
  	N += 1.0;
  	sumX += newval;
  	sumX2 += newval * newval;
! 
  	/*
  	 * If we're invoked by nodeAgg, we can cheat and modify our first
  	 * parameter in-place to reduce palloc overhead. Otherwise we construct a
--- 1983,1992 ----
  
  	N += 1.0;
  	sumX += newval;
+ 	CheckFloat8Val(sumX, isinf(transvalues[1]) || isinf(newval));
  	sumX2 += newval * newval;
! 	CheckFloat8Val(sumX2, isinf(transvalues[2]) || isinf(newval));
! 	
  	/*
  	 * If we're invoked by nodeAgg, we can cheat and modify our first
  	 * parameter in-place to reduce palloc overhead. Otherwise we construct a
***************
*** 2016,2023 ****
  
  	N += 1.0;
  	sumX += newval;
  	sumX2 += newval * newval;
! 
  	/*
  	 * If we're invoked by nodeAgg, we can cheat and modify our first
  	 * parameter in-place to reduce palloc overhead. Otherwise we construct a
--- 2038,2047 ----
  
  	N += 1.0;
  	sumX += newval;
+ 	CheckFloat4Val(sumX, isinf(transvalues[1]) || isinf(newval));
  	sumX2 += newval * newval;
! 	CheckFloat4Val(sumX2, isinf(transvalues[2]) || isinf(newval));
! 	
  	/*
  	 * If we're invoked by nodeAgg, we can cheat and modify our first
  	 * parameter in-place to reduce palloc overhead. Otherwise we construct a
***************
*** 2088,2093 ****
--- 2112,2118 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numerator, isinf(sumX2) || isinf(sumX));
  
  	/* Watch out for roundoff error producing a negative numerator */
  	if (numerator <= 0.0)
***************
*** 2116,2121 ****
--- 2141,2147 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numerator, isinf(sumX2) || isinf(sumX));
  
  	/* Watch out for roundoff error producing a negative numerator */
  	if (numerator <= 0.0)
***************
*** 2144,2149 ****
--- 2170,2176 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numerator, isinf(sumX2) || isinf(sumX));
  
  	/* Watch out for roundoff error producing a negative numerator */
  	if (numerator <= 0.0)
***************
*** 2172,2177 ****
--- 2199,2205 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numerator, isinf(sumX2) || isinf(sumX));
  
  	/* Watch out for roundoff error producing a negative numerator */
  	if (numerator <= 0.0)
***************
*** 2220,2230 ****
  
  	N += 1.0;
  	sumX += newvalX;
  	sumX2 += newvalX * newvalX;
  	sumY += newvalY;
  	sumY2 += newvalY * newvalY;
  	sumXY += newvalX * newvalY;
! 
  	/*
  	 * If we're invoked by nodeAgg, we can cheat and modify our first
  	 * parameter in-place to reduce palloc overhead. Otherwise we construct a
--- 2248,2263 ----
  
  	N += 1.0;
  	sumX += newvalX;
+ 	CheckFloat8Val(sumX, isinf(transvalues[1]) || isinf(newvalX));
  	sumX2 += newvalX * newvalX;
+ 	CheckFloat8Val(sumX2, isinf(transvalues[2]) || isinf(newvalX));
  	sumY += newvalY;
+ 	CheckFloat8Val(sumY, isinf(transvalues[3]) || isinf(newvalY));
  	sumY2 += newvalY * newvalY;
+ 	CheckFloat8Val(sumY2, isinf(transvalues[4]) || isinf(newvalY));
  	sumXY += newvalX * newvalY;
! 	CheckFloat8Val(sumXY, isinf(transvalues[5]) || isinf(newvalX) || isinf(newvalY));
! 	
  	/*
  	 * If we're invoked by nodeAgg, we can cheat and modify our first
  	 * parameter in-place to reduce palloc overhead. Otherwise we construct a
***************
*** 2282,2287 ****
--- 2315,2321 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numerator, isinf(sumX2) || isinf(sumX));
  
  	/* Watch out for roundoff error producing a negative numerator */
  	if (numerator <= 0.0)
***************
*** 2310,2315 ****
--- 2344,2350 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumY2 - sumY * sumY;
+ 	CheckFloat8Val(numerator, isinf(sumY2) || isinf(sumY));
  
  	/* Watch out for roundoff error producing a negative numerator */
  	if (numerator <= 0.0)
***************
*** 2340,2345 ****
--- 2375,2381 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumXY - sumX * sumY;
+ 	CheckFloat8Val(numerator, isinf(sumXY) || isinf(sumX) || isinf(sumY));
  
  	/* A negative result is valid here */
  
***************
*** 2406,2411 ****
--- 2442,2448 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumXY - sumX * sumY;
+ 	CheckFloat8Val(numerator, isinf(sumXY) || isinf(sumX) || isinf(sumY));
  
  	PG_RETURN_FLOAT8(numerator / (N * N));
  }
***************
*** 2432,2437 ****
--- 2469,2475 ----
  		PG_RETURN_NULL();
  
  	numerator = N * sumXY - sumX * sumY;
+ 	CheckFloat8Val(numerator, isinf(sumXY) || isinf(sumX) || isinf(sumY));
  
  	PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
  }
***************
*** 2464,2471 ****
--- 2502,2512 ----
  		PG_RETURN_NULL();
  
  	numeratorX = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numeratorX, isinf(sumX2) || isinf(sumX));
  	numeratorY = N * sumY2 - sumY * sumY;
+ 	CheckFloat8Val(numeratorY, isinf(sumY2) || isinf(sumY));
  	numeratorXY = N * sumXY - sumX * sumY;
+ 	CheckFloat8Val(numeratorXY, isinf(sumXY) || isinf(sumX) || isinf(sumY));
  	if (numeratorX <= 0 || numeratorY <= 0)
  		PG_RETURN_NULL();
  
***************
*** 2501,2508 ****
--- 2542,2552 ----
  		PG_RETURN_NULL();
  
  	numeratorX = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numeratorX, isinf(sumX2) || isinf(sumX));
  	numeratorY = N * sumY2 - sumY * sumY;
+ 	CheckFloat8Val(numeratorY, isinf(sumY2) || isinf(sumY));
  	numeratorXY = N * sumXY - sumX * sumY;
+ 	CheckFloat8Val(numeratorXY, isinf(sumXY) || isinf(sumX) || isinf(sumY));
  	if (numeratorX <= 0)
  		PG_RETURN_NULL();
  	/* per spec, horizontal line produces 1.0 */
***************
*** 2538,2544 ****
--- 2582,2590 ----
  		PG_RETURN_NULL();
  
  	numeratorX = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numeratorX, isinf(sumX2) || isinf(sumX));
  	numeratorXY = N * sumXY - sumX * sumY;
+ 	CheckFloat8Val(numeratorXY, isinf(sumXY) || isinf(sumX) || isinf(sumY));
  	if (numeratorX <= 0)
  		PG_RETURN_NULL();
  
***************
*** 2570,2576 ****
--- 2616,2624 ----
  		PG_RETURN_NULL();
  
  	numeratorX = N * sumX2 - sumX * sumX;
+ 	CheckFloat8Val(numeratorX, isinf(sumX2) || isinf(sumX));
  	numeratorXXY = sumY * sumX2 - sumX * sumXY;
+ 	CheckFloat8Val(numeratorXXY, isinf(sumY) || isinf(sumX2) || isinf(sumX) || isinf(sumXY));
  	if (numeratorX <= 0)
  		PG_RETURN_NULL();
  
***************
*** 2598,2604 ****
  	float8		result;
  
  	result = arg1 + arg2;
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2646,2652 ----
  	float8		result;
  
  	result = arg1 + arg2;
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2610,2616 ****
  	float8		result;
  
  	result = arg1 - arg2;
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2658,2664 ----
  	float8		result;
  
  	result = arg1 - arg2;
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2622,2628 ****
  	float8		result;
  
  	result = arg1 * arg2;
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2670,2676 ----
  	float8		result;
  
  	result = arg1 * arg2;
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2639,2645 ****
  				 errmsg("division by zero")));
  
  	result = arg1 / arg2;
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2687,2693 ----
  				 errmsg("division by zero")));
  
  	result = arg1 / arg2;
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2658,2664 ****
  
  	result = arg1 + arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2706,2712 ----
  
  	result = arg1 + arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2671,2677 ****
  
  	result = arg1 - arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2719,2725 ----
  
  	result = arg1 - arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2684,2690 ****
  
  	result = arg1 * arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2732,2738 ----
  
  	result = arg1 * arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
***************
*** 2702,2708 ****
  
  	result = arg1 / arg2;
  
! 	CheckFloat8Val(result);
  	PG_RETURN_FLOAT8(result);
  }
  
--- 2750,2756 ----
  
  	result = arg1 / arg2;
  
! 	CheckFloat8Val(result, isinf(arg1) || isinf(arg2));
  	PG_RETURN_FLOAT8(result);
  }
  
Index: src/backend/utils/adt/int.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/int.c,v
retrieving revision 1.75
diff -c -c -r1.75 int.c
*** src/backend/utils/adt/int.c	4 Oct 2006 00:29:59 -0000	1.75
--- src/backend/utils/adt/int.c	27 Dec 2006 18:43:26 -0000
***************
*** 1124,1129 ****
--- 1124,1134 ----
  		ereport(ERROR,
  				(errcode(ERRCODE_DIVISION_BY_ZERO),
  				 errmsg("division by zero")));
+ 
+ 	/* SELECT ((-2147483648)::int4) % (-1); causes a floating point exception */
+ 	if (arg1 == INT_MIN && arg2 == -1)
+ 		PG_RETURN_INT32(0);
+ 
  	/* No overflow is possible */
  
  	PG_RETURN_INT32(arg1 % arg2);
Index: src/test/regress/expected/float4.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/float4.out,v
retrieving revision 1.13
diff -c -c -r1.13 float4.out
*** src/test/regress/expected/float4.out	7 Apr 2005 01:51:40 -0000	1.13
--- src/test/regress/expected/float4.out	27 Dec 2006 18:43:28 -0000
***************
*** 72,78 ****
  SELECT ' INFINITY    x'::float4;
  ERROR:  invalid input syntax for type real: " INFINITY    x"
  SELECT 'Infinity'::float4 + 100.0;
! ERROR:  type "double precision" value out of range: overflow
  SELECT 'Infinity'::float4 / 'Infinity'::float4;
   ?column? 
  ----------
--- 72,82 ----
  SELECT ' INFINITY    x'::float4;
  ERROR:  invalid input syntax for type real: " INFINITY    x"
  SELECT 'Infinity'::float4 + 100.0;
!  ?column? 
! ----------
!  Infinity
! (1 row)
! 
  SELECT 'Infinity'::float4 / 'Infinity'::float4;
   ?column? 
  ----------
Index: src/test/regress/expected/float8.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/float8.out,v
retrieving revision 1.24
diff -c -c -r1.24 float8.out
*** src/test/regress/expected/float8.out	8 Jun 2005 21:15:29 -0000	1.24
--- src/test/regress/expected/float8.out	27 Dec 2006 18:43:28 -0000
***************
*** 72,78 ****
  SELECT ' INFINITY    x'::float8;
  ERROR:  invalid input syntax for type double precision: " INFINITY    x"
  SELECT 'Infinity'::float8 + 100.0;
! ERROR:  type "double precision" value out of range: overflow
  SELECT 'Infinity'::float8 / 'Infinity'::float8;
   ?column? 
  ----------
--- 72,82 ----
  SELECT ' INFINITY    x'::float8;
  ERROR:  invalid input syntax for type double precision: " INFINITY    x"
  SELECT 'Infinity'::float8 + 100.0;
!  ?column? 
! ----------
!  Infinity
! (1 row)
! 
  SELECT 'Infinity'::float8 / 'Infinity'::float8;
   ?column? 
  ----------
