Tom Lane wrote: > Bruce Momjian <[EMAIL PROTECTED]> writes: > > OK, are you saying that there is a signal we are ignoring for > > overflow/underflow, or that we should just silently overflow/underflow > > and not throw an error? > > Silent underflow is fine with me; it's the norm in most all float > implementations and won't surprise anyone. For overflow I'm OK with > either returning infinity or throwing an error --- but if an error, > it should only be about inf-out-with-non-inf-in, not comparisons to any > artificial MAX/MIN values.
OK, I am happy to remove the MIN/MAX comparisons. Those were in the original code. The attached, updated patch creates a single CHECKFLOATVAL() macro that does the overflow/underflow comparisons and throws an error. This also reduces the isinf() calls. Should I be concerned we are now duplicating the error text in all call sites? Regression wording modified now that float4/float8 checks are merged. I haven't update the platform-specific float* expected files yet, but will on commit. -- Bruce Momjian [EMAIL PROTECTED] EnterpriseDB http://www.enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
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 30 Dec 2006 18:19:57 -0000 *************** *** 12,59 **** * *------------------------------------------------------------------------- */ - /*---------- - * OLD COMMENTS - * Basic float4 ops: - * float4in, float4out, float4recv, float4send - * float4abs, float4um, float4up - * Basic float8 ops: - * float8in, float8out, float8recv, float8send - * float8abs, float8um, float8up - * Arithmetic operators: - * float4pl, float4mi, float4mul, float4div - * float8pl, float8mi, float8mul, float8div - * Comparison operators: - * float4eq, float4ne, float4lt, float4le, float4gt, float4ge, float4cmp - * float8eq, float8ne, float8lt, float8le, float8gt, float8ge, float8cmp - * Conversion routines: - * ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2 - * - * Random float8 ops: - * dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1 - * Arithmetic operators: - * float48pl, float48mi, float48mul, float48div - * float84pl, float84mi, float84mul, float84div - * Comparison operators: - * float48eq, float48ne, float48lt, float48le, float48gt, float48ge - * float84eq, float84ne, float84lt, float84le, float84gt, float84ge - * - * (You can do the arithmetic and comparison stuff using conversion - * routines, but then you pay the overhead of invoking a separate - * conversion function...) - * - * XXX GLUESOME STUFF. FIX IT! -AY '94 - * - * Added some additional conversion routines and cleaned up - * a bit of the existing code. Need to change the error checking - * for calls to pow(), exp() since on some machines (my Linux box - * included) these routines do not set errno. - tgl 97/05/10 - *---------- - */ #include "postgres.h" #include <ctype.h> - #include <float.h> #include <math.h> #include <limits.h> /* for finite() on Solaris */ --- 12,20 ---- *************** *** 91,111 **** #define MAXFLOATWIDTH 64 #define MAXDOUBLEWIDTH 128 ! /* ========== USER I/O ROUTINES ========== */ ! #define FLOAT4_MAX FLT_MAX ! #define FLOAT4_MIN FLT_MIN ! #define FLOAT8_MAX DBL_MAX ! #define FLOAT8_MIN DBL_MIN /* Configurable GUC parameter */ 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); --- 52,81 ---- #define MAXFLOATWIDTH 64 #define MAXDOUBLEWIDTH 128 ! /* ! * check to see if a float4/8 val has underflowed or overflowed ! */ ! #define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid) \ ! do { \ ! if (isinf(val) && !(inf_is_valid)) \ ! ereport(ERROR, \ ! (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \ ! errmsg("value out of range: overflow"))); \ ! \ ! if ((val) == 0.0 && !(zero_is_valid)) \ ! ereport(ERROR, \ ! (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \ ! errmsg("value out of range: underflow"))); \ ! } while(0) ! /* ========== USER I/O ROUTINES ========== */ /* Configurable GUC parameter */ int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */ static int float4_cmp_internal(float4 a, float4 b); static int float8_cmp_internal(float8 a, float8 b); *************** *** 205,248 **** /* - * check to see if a float4 val is outside of the FLOAT4_MIN, - * FLOAT4_MAX bounds. - * - * 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"))); - if (val != 0.0 && fabs(val) < FLOAT4_MIN) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("type \"real\" value out of range: underflow"))); - } - - /* - * check to see if a float8 val is outside of the FLOAT8_MIN, - * FLOAT8_MAX bounds. - * - * 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), - errmsg("type \"double precision\" value out of range: underflow"))); - } - - /* * float4in - converts "num" to float * restricted syntax: * {<sp>} [+|-] {digit} [.{digit}] [<exp>] --- 175,180 ---- *************** *** 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); } --- 301,307 ---- * if we get here, we have a legal double, still need to check to see if * it's a legal float4 */ ! CHECKFLOATVAL((float4) val, isinf(val), val == 0); 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); } --- 489,495 ---- errmsg("invalid input syntax for type double precision: \"%s\"", orig_num))); ! CHECKFLOATVAL(val, true, true); PG_RETURN_FLOAT8(val); } *************** *** 652,659 **** float4um(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); ! PG_RETURN_FLOAT4((float4) -arg1); } Datum --- 582,593 ---- float4um(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); + float4 result; + + result = ((arg1 != 0) ? -(arg1) : arg1); ! CHECKFLOATVAL(result, isinf(arg1), true); ! 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); } --- 639,646 ---- 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); } --- 655,661 ---- result = ((arg1 != 0) ? -(arg1) : arg1); ! CHECKFLOATVAL(result, isinf(arg1), true); PG_RETURN_FLOAT8(result); } *************** *** 783,793 **** { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! double result; result = arg1 + arg2; ! CheckFloat4Val(result); ! PG_RETURN_FLOAT4((float4) result); } Datum --- 713,723 ---- { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! float4 result; result = arg1 + arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); ! PG_RETURN_FLOAT4(result); } Datum *************** *** 795,805 **** { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! double result; result = arg1 - arg2; ! CheckFloat4Val(result); ! PG_RETURN_FLOAT4((float4) result); } Datum --- 725,735 ---- { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! float4 result; result = arg1 - arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); ! PG_RETURN_FLOAT4(result); } Datum *************** *** 807,817 **** { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! double result; result = arg1 * arg2; ! CheckFloat4Val(result); ! PG_RETURN_FLOAT4((float4) result); } Datum --- 737,748 ---- { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! float4 result; result = arg1 * arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), ! arg1 == 0 || arg2 == 0); ! PG_RETURN_FLOAT4(result); } Datum *************** *** 819,825 **** { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! double result; if (arg2 == 0.0) ereport(ERROR, --- 750,756 ---- { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); ! float4 result; if (arg2 == 0.0) ereport(ERROR, *************** *** 827,836 **** errmsg("division by zero"))); /* Do division in float8, then check for overflow */ ! result = (float8) arg1 / (float8) arg2; ! CheckFloat4Val(result); ! PG_RETURN_FLOAT4((float4) result); } /* --- 758,767 ---- errmsg("division by zero"))); /* Do division in float8, then check for overflow */ ! result = arg1 / arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); ! PG_RETURN_FLOAT4(result); } /* *************** *** 848,854 **** result = arg1 + arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 779,785 ---- result = arg1 + arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 861,867 **** result = arg1 - arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 792,798 ---- result = arg1 - arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 874,880 **** result = arg1 * arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 805,812 ---- result = arg1 * arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), ! arg1 == 0 || arg2 == 0); PG_RETURN_FLOAT8(result); } *************** *** 892,898 **** result = arg1 / arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 824,830 ---- result = arg1 / arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT8(result); } *************** *** 1142,1148 **** { float8 num = PG_GETARG_FLOAT8(0); ! CheckFloat4Val(num); PG_RETURN_FLOAT4((float4) num); } --- 1074,1080 ---- { float8 num = PG_GETARG_FLOAT8(0); ! CHECKFLOATVAL((float4) num, isinf(num), true); 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"))); --- 1089,1096 ---- 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"))); *************** *** 1174,1188 **** dtoi2(PG_FUNCTION_ARGS) { 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"))); ! result = (int16) rint(num); ! PG_RETURN_INT16(result); } --- 1107,1119 ---- dtoi2(PG_FUNCTION_ARGS) { float8 num = PG_GETARG_FLOAT8(0); ! if (num < SHRT_MIN || num > SHRT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); ! PG_RETURN_INT16((int16) rint(num)); } *************** *** 1193,1202 **** i4tod(PG_FUNCTION_ARGS) { int32 num = PG_GETARG_INT32(0); - float8 result; ! result = num; ! PG_RETURN_FLOAT8(result); } --- 1124,1131 ---- i4tod(PG_FUNCTION_ARGS) { int32 num = PG_GETARG_INT32(0); ! PG_RETURN_FLOAT8((float8) num); } *************** *** 1207,1216 **** i2tod(PG_FUNCTION_ARGS) { int16 num = PG_GETARG_INT16(0); - float8 result; ! result = num; ! PG_RETURN_FLOAT8(result); } --- 1136,1143 ---- i2tod(PG_FUNCTION_ARGS) { int16 num = PG_GETARG_INT16(0); ! PG_RETURN_FLOAT8((float8) num); } *************** *** 1221,1235 **** ftoi4(PG_FUNCTION_ARGS) { 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"))); ! result = (int32) rint(num); ! PG_RETURN_INT32(result); } --- 1148,1160 ---- ftoi4(PG_FUNCTION_ARGS) { float4 num = PG_GETARG_FLOAT4(0); ! if (num < INT_MIN || num > INT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); ! PG_RETURN_INT32((int32) rint(num)); } *************** *** 1240,1268 **** ftoi2(PG_FUNCTION_ARGS) { 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"))); ! result = (int16) rint(num); ! PG_RETURN_INT16(result); } /* ! * i4tof - converts an int4 number to a float8 number */ Datum i4tof(PG_FUNCTION_ARGS) { int32 num = PG_GETARG_INT32(0); - float4 result; ! result = num; ! PG_RETURN_FLOAT4(result); } --- 1165,1189 ---- ftoi2(PG_FUNCTION_ARGS) { float4 num = PG_GETARG_FLOAT4(0); ! if (num < SHRT_MIN || num > SHRT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); ! PG_RETURN_INT16((int16) rint(num)); } /* ! * i4tof - converts an int4 number to a float4 number */ Datum i4tof(PG_FUNCTION_ARGS) { int32 num = PG_GETARG_INT32(0); ! PG_RETURN_FLOAT4((float4) num); } *************** *** 1273,1282 **** i2tof(PG_FUNCTION_ARGS) { int16 num = PG_GETARG_INT16(0); - float4 result; ! result = num; ! PG_RETURN_FLOAT4(result); } --- 1194,1201 ---- i2tof(PG_FUNCTION_ARGS) { int16 num = PG_GETARG_INT16(0); ! PG_RETURN_FLOAT4((float4) num); } *************** *** 1395,1405 **** dround(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); - float8 result; - - result = rint(arg1); ! PG_RETURN_FLOAT8(result); } /* --- 1314,1321 ---- dround(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); ! PG_RETURN_FLOAT8(rint(arg1)); } /* *************** *** 1485,1491 **** result = sqrt(arg1); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1401,1407 ---- result = sqrt(arg1); ! CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } *************** *** 1500,1505 **** --- 1416,1422 ---- float8 result; result = cbrt(arg1); + CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } *************** *** 1530,1545 **** */ errno = 0; result = pow(arg1, arg2); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("result is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1447,1458 ---- */ errno = 0; result = pow(arg1, arg2); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("result is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT8(result); } *************** *** 1555,1575 **** /* * We must check both for errno getting set and for a NaN result, in order ! * to deal with the vagaries of different platforms. Also, a zero result ! * implies unreported underflow. */ errno = 0; result = exp(arg1); ! if (errno != 0 || result == 0.0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("result is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1468,1483 ---- /* * We must check both for errno getting set and for a NaN result, in order ! * to deal with the vagaries of different platforms. */ errno = 0; result = exp(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("result is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1), false); PG_RETURN_FLOAT8(result); } *************** *** 1598,1604 **** result = log(arg1); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1506,1512 ---- result = log(arg1); ! CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result); } *************** *** 1628,1634 **** result = log10(arg1); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1536,1542 ---- result = log10(arg1); ! CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result); } *************** *** 1644,1659 **** errno = 0; result = acos(arg1); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1552,1563 ---- errno = 0; result = acos(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1), true); PG_RETURN_FLOAT8(result); } *************** *** 1669,1684 **** errno = 0; result = asin(arg1); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1573,1584 ---- errno = 0; result = asin(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1), true); PG_RETURN_FLOAT8(result); } *************** *** 1694,1709 **** errno = 0; result = atan(arg1); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1594,1605 ---- errno = 0; result = atan(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1), true); PG_RETURN_FLOAT8(result); } *************** *** 1720,1735 **** errno = 0; result = atan2(arg1, arg2); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1616,1627 ---- errno = 0; result = atan2(arg1, arg2); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 1745,1760 **** errno = 0; result = cos(arg1); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1637,1648 ---- errno = 0; result = cos(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1), true); PG_RETURN_FLOAT8(result); } *************** *** 1770,1786 **** errno = 0; result = tan(arg1); ! if (errno != 0 || result == 0.0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); result = 1.0 / result; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1658,1670 ---- errno = 0; result = tan(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); result = 1.0 / result; ! CHECKFLOATVAL(result, true /* cotan(pi/2) == inf */, true); PG_RETURN_FLOAT8(result); } *************** *** 1796,1811 **** errno = 0; result = sin(arg1); ! if (errno != 0 ! #ifdef HAVE_FINITE ! || !finite(result) ! #endif ! ) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1680,1691 ---- errno = 0; result = sin(arg1); ! if (errno != 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, isinf(arg1), true); 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); } --- 1710,1716 ---- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); ! CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */, true); PG_RETURN_FLOAT8(result); } *************** *** 1846,1852 **** result = arg1 * (180.0 / M_PI); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1726,1732 ---- result = arg1 * (180.0 / M_PI); ! CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } *************** *** 1872,1878 **** result = arg1 * (M_PI / 180.0); ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 1752,1758 ---- result = arg1 * (M_PI / 180.0); ! CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); 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 --- 1843,1852 ---- N += 1.0; sumX += newval; + CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true); sumX2 += newval * newval; ! CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true); ! /* * If we're invoked by nodeAgg, we can cheat and modify our first * parameter in-place to reduce palloc overhead. Otherwise we construct a *************** *** 1999,2023 **** float4_accum(PG_FUNCTION_ARGS) { ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); ! float4 newval4 = PG_GETARG_FLOAT4(1); float8 *transvalues; float8 N, sumX, ! sumX2, ! newval; transvalues = check_float8_array(transarray, "float4_accum", 3); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; - /* Do arithmetic in float8 for best accuracy */ - newval = newval4; - 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 --- 1881,1904 ---- float4_accum(PG_FUNCTION_ARGS) { ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); ! /* do computations as float8 */ ! float8 newval = PG_GETARG_FLOAT4(1); float8 *transvalues; float8 N, sumX, ! sumX2; transvalues = check_float8_array(transarray, "float4_accum", 3); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; N += 1.0; sumX += newval; + CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true); sumX2 += newval * newval; ! CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true); ! /* * 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 **** --- 1969,1975 ---- PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) *************** *** 2116,2121 **** --- 1998,2004 ---- PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) *************** *** 2144,2149 **** --- 2027,2033 ---- PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) *************** *** 2172,2177 **** --- 2056,2062 ---- PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); /* 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 --- 2105,2121 ---- N += 1.0; sumX += newvalX; + CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newvalX), true); sumX2 += newvalX * newvalX; + CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newvalX), true); sumY += newvalY; + CHECKFLOATVAL(sumY, isinf(transvalues[3]) || isinf(newvalY), true); sumY2 += newvalY * newvalY; + CHECKFLOATVAL(sumY2, isinf(transvalues[4]) || isinf(newvalY), true); sumXY += newvalX * newvalY; ! CHECKFLOATVAL(sumXY, isinf(transvalues[5]) || isinf(newvalX) || ! isinf(newvalY), true); ! /* * 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 **** --- 2173,2179 ---- PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) *************** *** 2310,2315 **** --- 2202,2208 ---- PG_RETURN_NULL(); numerator = N * sumY2 - sumY * sumY; + CHECKFLOATVAL(numerator, isinf(sumY2) || isinf(sumY), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) *************** *** 2340,2345 **** --- 2233,2240 ---- PG_RETURN_NULL(); numerator = N * sumXY - sumX * sumY; + CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); /* A negative result is valid here */ *************** *** 2406,2411 **** --- 2301,2308 ---- PG_RETURN_NULL(); numerator = N * sumXY - sumX * sumY; + CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); PG_RETURN_FLOAT8(numerator / (N * N)); } *************** *** 2432,2437 **** --- 2329,2336 ---- PG_RETURN_NULL(); numerator = N * sumXY - sumX * sumY; + CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); PG_RETURN_FLOAT8(numerator / (N * (N - 1.0))); } *************** *** 2464,2471 **** --- 2363,2374 ---- PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorY = N * sumY2 - sumY * sumY; + CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true); numeratorXY = N * sumXY - sumX * sumY; + CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); if (numeratorX <= 0 || numeratorY <= 0) PG_RETURN_NULL(); *************** *** 2501,2508 **** --- 2404,2415 ---- PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorY = N * sumY2 - sumY * sumY; + CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true); numeratorXY = N * sumXY - sumX * sumY; + CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); if (numeratorX <= 0) PG_RETURN_NULL(); /* per spec, horizontal line produces 1.0 */ *************** *** 2538,2544 **** --- 2445,2454 ---- PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorXY = N * sumXY - sumX * sumY; + CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); if (numeratorX <= 0) PG_RETURN_NULL(); *************** *** 2570,2576 **** --- 2480,2489 ---- PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; + CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorXXY = sumY * sumX2 - sumX * sumXY; + CHECKFLOATVAL(numeratorXXY, isinf(sumY) || isinf(sumX2) || + isinf(sumX) || isinf(sumXY), true); if (numeratorX <= 0) PG_RETURN_NULL(); *************** *** 2598,2604 **** float8 result; result = arg1 + arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2511,2517 ---- float8 result; result = arg1 + arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 2610,2616 **** float8 result; result = arg1 - arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2523,2529 ---- float8 result; result = arg1 - arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 2622,2628 **** float8 result; result = arg1 * arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2535,2542 ---- float8 result; result = arg1 * arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), ! arg1 == 0 || arg2 == 0); PG_RETURN_FLOAT8(result); } *************** *** 2639,2645 **** errmsg("division by zero"))); result = arg1 / arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2553,2559 ---- errmsg("division by zero"))); result = arg1 / arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT8(result); } *************** *** 2658,2664 **** result = arg1 + arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2572,2578 ---- result = arg1 + arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 2671,2677 **** result = arg1 - arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2585,2591 ---- result = arg1 - arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); PG_RETURN_FLOAT8(result); } *************** *** 2684,2690 **** result = arg1 * arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2598,2605 ---- result = arg1 * arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), ! arg1 == 0 || arg2 == 0); PG_RETURN_FLOAT8(result); } *************** *** 2702,2708 **** result = arg1 / arg2; ! CheckFloat8Val(result); PG_RETURN_FLOAT8(result); } --- 2617,2623 ---- result = arg1 / arg2; ! CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); 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 30 Dec 2006 18:19:57 -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-exp-three-digits.out =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/expected/float4-exp-three-digits.out,v retrieving revision 1.7 diff -c -c -r1.7 float4-exp-three-digits.out *** src/test/regress/expected/float4-exp-three-digits.out 7 Apr 2005 01:51:40 -0000 1.7 --- src/test/regress/expected/float4-exp-three-digits.out 30 Dec 2006 18:19:59 -0000 *************** *** 8,20 **** INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20'); INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e40'); ERROR: type "real" value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40'); ERROR: type "real" value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40'); ERROR: type "real" value out of range: underflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40'); ERROR: type "real" value out of range: underflow -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); --- 8,20 ---- INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20'); INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e50'); ERROR: type "real" value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e50'); ERROR: type "real" value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-50'); ERROR: type "real" value out of range: underflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-50'); ERROR: type "real" value out of range: underflow -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); 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 30 Dec 2006 18:19:59 -0000 *************** *** 8,21 **** INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20'); INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e40'); ! ERROR: type "real" value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40'); ! ERROR: type "real" value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40'); ! ERROR: type "real" value out of range: underflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40'); ! ERROR: type "real" value out of range: underflow -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); ERROR: invalid input syntax for type real: "" --- 8,21 ---- INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20'); INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e50'); ! ERROR: value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e50'); ! ERROR: value out of range: overflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-50'); ! ERROR: value out of range: underflow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-50'); ! ERROR: value out of range: underflow -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); ERROR: invalid input syntax for type real: "" *************** *** 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 30 Dec 2006 18:19:59 -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? ---------- *************** *** 342,356 **** SET f1 = FLOAT8_TBL.f1 * '-1' WHERE FLOAT8_TBL.f1 > '0.0'; SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f; ! ERROR: type "double precision" value out of range: overflow SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f; ! ERROR: result is out of range SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; ERROR: cannot take logarithm of zero SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; ERROR: cannot take logarithm of a negative number SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f; ! ERROR: result is out of range SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f; ERROR: division by zero SELECT '' AS five, * FROM FLOAT8_TBL; --- 346,360 ---- SET f1 = FLOAT8_TBL.f1 * '-1' WHERE FLOAT8_TBL.f1 > '0.0'; SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f; ! ERROR: value out of range: overflow SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f; ! ERROR: value out of range: overflow SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; ERROR: cannot take logarithm of zero SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; ERROR: cannot take logarithm of a negative number SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f; ! ERROR: value out of range: underflow SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f; ERROR: division by zero SELECT '' AS five, * FROM FLOAT8_TBL; Index: src/test/regress/sql/float4.sql =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/sql/float4.sql,v retrieving revision 1.8 diff -c -c -r1.8 float4.sql *** src/test/regress/sql/float4.sql 7 Apr 2005 01:51:41 -0000 1.8 --- src/test/regress/sql/float4.sql 30 Dec 2006 18:19:59 -0000 *************** *** 11,20 **** INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e40'); ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40'); ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40'); ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40'); -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES (''); --- 11,20 ---- INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); -- test for over and under flow ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e50'); ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e50'); ! INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-50'); ! INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-50'); -- bad input INSERT INTO FLOAT4_TBL(f1) VALUES ('');
---------------------------(end of broadcast)--------------------------- TIP 2: Don't 'kill -9' the postmaster