]> granicus.if.org Git - postgresql/commitdiff
Fix float4/8 to handle Infinity and Nan consistently, e.g. Infinity is a
authorBruce Momjian <bruce@momjian.us>
Tue, 2 Jan 2007 20:00:50 +0000 (20:00 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 2 Jan 2007 20:00:50 +0000 (20:00 +0000)
valid result from a computation if one of the input values was infinity.
The previous code assumed an operation that returned infinity was an
overflow.

Handle underflow/overflow consistently, and add checks for aggregate
overflow.

Consistently prevent Inf/Nan from being cast to integer data types.

Fix INT_MIN % -1 to prevent overflow.

Update regression results for new error text.

Per report from Roman Kononov.

src/backend/utils/adt/float.c
src/backend/utils/adt/int.c
src/test/regress/expected/float4-exp-three-digits.out
src/test/regress/expected/float4.out
src/test/regress/expected/float8-exp-three-digits-win32.out
src/test/regress/expected/float8-small-is-zero.out
src/test/regress/expected/float8-small-is-zero_1.out
src/test/regress/expected/float8.out
src/test/regress/sql/float4.sql

index 2b578ddf4e6ab38b12a2b1442aefdfdff285a4a4..4c081540a6f9516c3f05de4482761e405d6e5d33 100644 (file)
@@ -8,52 +8,13 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.131 2006/12/23 02:13:24 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.132 2007/01/02 20:00:49 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
-/*----------
- * 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 */
@@ -91,21 +52,30 @@ static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
 #define MAXFLOATWIDTH  64
 #define MAXDOUBLEWIDTH 128
 
-/* ========== USER I/O ROUTINES ========== */
+/*
+ * 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)
 
 
-#define FLOAT4_MAX              FLT_MAX
-#define FLOAT4_MIN              FLT_MIN
-#define FLOAT8_MAX              DBL_MAX
-#define FLOAT8_MIN              DBL_MIN
+/* ========== USER I/O ROUTINES ========== */
 
 
 /* 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);
 
@@ -204,44 +174,6 @@ is_infinite(double val)
 }
 
 
-/*
- * 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:
@@ -369,8 +301,7 @@ float4in(PG_FUNCTION_ARGS)
         * 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);
+       CHECKFLOATVAL((float4) val, isinf(val), val == 0);
 
        PG_RETURN_FLOAT4((float4) val);
 }
@@ -558,8 +489,7 @@ float8in(PG_FUNCTION_ARGS)
                         errmsg("invalid input syntax for type double precision: \"%s\"",
                                        orig_num)));
 
-       if (!isinf(val))
-               CheckFloat8Val(val);
+       CHECKFLOATVAL(val, true, true);
 
        PG_RETURN_FLOAT8(val);
 }
@@ -652,8 +582,12 @@ Datum
 float4um(PG_FUNCTION_ARGS)
 {
        float4          arg1 = PG_GETARG_FLOAT4(0);
+       float4          result;
+
+       result = ((arg1 != 0) ? -(arg1) : arg1);
 
-       PG_RETURN_FLOAT4((float4) -arg1);
+       CHECKFLOATVAL(result, isinf(arg1), true);
+       PG_RETURN_FLOAT4(result);
 }
 
 Datum
@@ -705,12 +639,8 @@ Datum
 float8abs(PG_FUNCTION_ARGS)
 {
        float8          arg1 = PG_GETARG_FLOAT8(0);
-       float8          result;
-
-       result = fabs(arg1);
 
-       CheckFloat8Val(result);
-       PG_RETURN_FLOAT8(result);
+       PG_RETURN_FLOAT8(fabs(arg1));
 }
 
 
@@ -725,7 +655,7 @@ float8um(PG_FUNCTION_ARGS)
 
        result = ((arg1 != 0) ? -(arg1) : arg1);
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -781,13 +711,20 @@ float8smaller(PG_FUNCTION_ARGS)
 Datum
 float4pl(PG_FUNCTION_ARGS)
 {
-       float4          arg1 = PG_GETARG_FLOAT4(0);
-       float4          arg2 = PG_GETARG_FLOAT4(1);
-       double          result;
+       float8          arg1 = PG_GETARG_FLOAT4(0);
+       float8          arg2 = PG_GETARG_FLOAT4(1);
+       float4          result;
 
        result = arg1 + arg2;
-       CheckFloat4Val(result);
-       PG_RETURN_FLOAT4((float4) result);
+       /*
+        *      There isn't any way to check for underflow of addition/subtraction
+        *      because numbers near the underflow value have been already been
+        *      to the point where we can't detect the that the two values
+        *      were originally different, e.g. on x86, '1e-45'::float4 ==
+        *      '2e-45'::float4 == 1.4013e-45.
+        */
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
+       PG_RETURN_FLOAT4(result);
 }
 
 Datum
@@ -795,11 +732,11 @@ float4mi(PG_FUNCTION_ARGS)
 {
        float4          arg1 = PG_GETARG_FLOAT4(0);
        float4          arg2 = PG_GETARG_FLOAT4(1);
-       double          result;
+       float4          result;
 
        result = arg1 - arg2;
-       CheckFloat4Val(result);
-       PG_RETURN_FLOAT4((float4) result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
+       PG_RETURN_FLOAT4(result);
 }
 
 Datum
@@ -807,11 +744,12 @@ float4mul(PG_FUNCTION_ARGS)
 {
        float4          arg1 = PG_GETARG_FLOAT4(0);
        float4          arg2 = PG_GETARG_FLOAT4(1);
-       double          result;
+       float4          result;
 
        result = arg1 * arg2;
-       CheckFloat4Val(result);
-       PG_RETURN_FLOAT4((float4) result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
+                                       arg1 == 0 || arg2 == 0);
+       PG_RETURN_FLOAT4(result);
 }
 
 Datum
@@ -819,7 +757,7 @@ float4div(PG_FUNCTION_ARGS)
 {
        float4          arg1 = PG_GETARG_FLOAT4(0);
        float4          arg2 = PG_GETARG_FLOAT4(1);
-       double          result;
+       float4          result;
 
        if (arg2 == 0.0)
                ereport(ERROR,
@@ -827,10 +765,10 @@ float4div(PG_FUNCTION_ARGS)
                                 errmsg("division by zero")));
 
        /* Do division in float8, then check for overflow */
-       result = (float8) arg1 / (float8) arg2;
+       result = arg1 / arg2;
 
-       CheckFloat4Val(result);
-       PG_RETURN_FLOAT4((float4) result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
+       PG_RETURN_FLOAT4(result);
 }
 
 /*
@@ -848,7 +786,7 @@ float8pl(PG_FUNCTION_ARGS)
 
        result = arg1 + arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -861,7 +799,7 @@ float8mi(PG_FUNCTION_ARGS)
 
        result = arg1 - arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -874,7 +812,8 @@ float8mul(PG_FUNCTION_ARGS)
 
        result = arg1 * arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
+                                       arg1 == 0 || arg2 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -892,7 +831,7 @@ float8div(PG_FUNCTION_ARGS)
 
        result = arg1 / arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1142,7 +1081,7 @@ dtof(PG_FUNCTION_ARGS)
 {
        float8          num = PG_GETARG_FLOAT8(0);
 
-       CheckFloat4Val(num);
+       CHECKFLOATVAL((float4) num, isinf(num), num == 0);
 
        PG_RETURN_FLOAT4((float4) num);
 }
@@ -1157,7 +1096,8 @@ dtoi4(PG_FUNCTION_ARGS)
        float8          num = PG_GETARG_FLOAT8(0);
        int32           result;
 
-       if (num < INT_MIN || num > INT_MAX)
+       /* '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,15 +1114,13 @@ Datum
 dtoi2(PG_FUNCTION_ARGS)
 {
        float8          num = PG_GETARG_FLOAT8(0);
-       int16           result;
 
-       if (num < SHRT_MIN || num > SHRT_MAX)
+       if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("smallint out of range")));
 
-       result = (int16) rint(num);
-       PG_RETURN_INT16(result);
+       PG_RETURN_INT16((int16) rint(num));
 }
 
 
@@ -1193,10 +1131,8 @@ Datum
 i4tod(PG_FUNCTION_ARGS)
 {
        int32           num = PG_GETARG_INT32(0);
-       float8          result;
 
-       result = num;
-       PG_RETURN_FLOAT8(result);
+       PG_RETURN_FLOAT8((float8) num);
 }
 
 
@@ -1207,10 +1143,8 @@ Datum
 i2tod(PG_FUNCTION_ARGS)
 {
        int16           num = PG_GETARG_INT16(0);
-       float8          result;
 
-       result = num;
-       PG_RETURN_FLOAT8(result);
+       PG_RETURN_FLOAT8((float8) num);
 }
 
 
@@ -1221,15 +1155,13 @@ Datum
 ftoi4(PG_FUNCTION_ARGS)
 {
        float4          num = PG_GETARG_FLOAT4(0);
-       int32           result;
 
-       if (num < INT_MIN || num > 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")));
 
-       result = (int32) rint(num);
-       PG_RETURN_INT32(result);
+       PG_RETURN_INT32((int32) rint(num));
 }
 
 
@@ -1240,29 +1172,25 @@ Datum
 ftoi2(PG_FUNCTION_ARGS)
 {
        float4          num = PG_GETARG_FLOAT4(0);
-       int16           result;
 
-       if (num < SHRT_MIN || num > SHRT_MAX)
+       if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("smallint out of range")));
 
-       result = (int16) rint(num);
-       PG_RETURN_INT16(result);
+       PG_RETURN_INT16((int16) rint(num));
 }
 
 
 /*
- *             i4tof                   - converts an int4 number to a float8 number
+ *             i4tof                   - converts an int4 number to a float4 number
  */
 Datum
 i4tof(PG_FUNCTION_ARGS)
 {
        int32           num = PG_GETARG_INT32(0);
-       float4          result;
 
-       result = num;
-       PG_RETURN_FLOAT4(result);
+       PG_RETURN_FLOAT4((float4) num);
 }
 
 
@@ -1273,10 +1201,8 @@ Datum
 i2tof(PG_FUNCTION_ARGS)
 {
        int16           num = PG_GETARG_INT16(0);
-       float4          result;
 
-       result = num;
-       PG_RETURN_FLOAT4(result);
+       PG_RETURN_FLOAT4((float4) num);
 }
 
 
@@ -1395,11 +1321,8 @@ Datum
 dround(PG_FUNCTION_ARGS)
 {
        float8          arg1 = PG_GETARG_FLOAT8(0);
-       float8          result;
-
-       result = rint(arg1);
 
-       PG_RETURN_FLOAT8(result);
+       PG_RETURN_FLOAT8(rint(arg1));
 }
 
 /*
@@ -1485,7 +1408,7 @@ dsqrt(PG_FUNCTION_ARGS)
 
        result = sqrt(arg1);
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1500,6 +1423,7 @@ dcbrt(PG_FUNCTION_ARGS)
        float8          result;
 
        result = cbrt(arg1);
+       CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1530,16 +1454,12 @@ dpow(PG_FUNCTION_ARGS)
         */
        errno = 0;
        result = pow(arg1, arg2);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("result is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1555,21 +1475,16 @@ dexp(PG_FUNCTION_ARGS)
 
        /*
         * 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.
+        * to deal with the vagaries of different platforms.
         */
        errno = 0;
        result = exp(arg1);
-       if (errno != 0 || result == 0.0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("result is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), false);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1598,7 +1513,7 @@ dlog1(PG_FUNCTION_ARGS)
 
        result = log(arg1);
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1628,7 +1543,7 @@ dlog10(PG_FUNCTION_ARGS)
 
        result = log10(arg1);
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1644,16 +1559,12 @@ dacos(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = acos(arg1);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1669,16 +1580,12 @@ dasin(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = asin(arg1);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1694,16 +1601,12 @@ datan(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = atan(arg1);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1720,16 +1623,12 @@ datan2(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = atan2(arg1, arg2);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1745,16 +1644,12 @@ dcos(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = cos(arg1);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1770,17 +1665,13 @@ dcot(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = tan(arg1);
-       if (errno != 0 || result == 0.0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
        result = 1.0 / result;
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, true /* cotan(pi/2) == inf */, true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1796,16 +1687,12 @@ dsin(PG_FUNCTION_ARGS)
 
        errno = 0;
        result = sin(arg1);
-       if (errno != 0
-#ifdef HAVE_FINITE
-               || !finite(result)
-#endif
-               )
+       if (errno != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1830,7 +1717,7 @@ dtan(PG_FUNCTION_ARGS)
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("input is out of range")));
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */, true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1846,7 +1733,7 @@ degrees(PG_FUNCTION_ARGS)
 
        result = arg1 * (180.0 / M_PI);
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1872,7 +1759,7 @@ radians(PG_FUNCTION_ARGS)
 
        result = arg1 * (M_PI / 180.0);
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -1963,8 +1850,10 @@ float8_accum(PG_FUNCTION_ARGS)
 
        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,25 +1888,24 @@ Datum
 float4_accum(PG_FUNCTION_ARGS)
 {
        ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
-       float4          newval4 = PG_GETARG_FLOAT4(1);
+       /* do computations as float8 */
+       float8          newval = PG_GETARG_FLOAT4(1);
        float8     *transvalues;
        float8          N,
                                sumX,
-                               sumX2,
-                               newval;
+                               sumX2;
 
        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;
+       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,6 +1976,7 @@ float8_var_pop(PG_FUNCTION_ARGS)
                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,6 +2005,7 @@ float8_var_samp(PG_FUNCTION_ARGS)
                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,6 +2034,7 @@ float8_stddev_pop(PG_FUNCTION_ARGS)
                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,6 +2063,7 @@ float8_stddev_samp(PG_FUNCTION_ARGS)
                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,11 +2112,17 @@ float8_regr_accum(PG_FUNCTION_ARGS)
 
        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,6 +2180,7 @@ float8_regr_sxx(PG_FUNCTION_ARGS)
                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,6 +2209,7 @@ float8_regr_syy(PG_FUNCTION_ARGS)
                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,6 +2240,8 @@ float8_regr_sxy(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
 
        numerator = N * sumXY - sumX * sumY;
+       CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
+                                       isinf(sumY), true);
 
        /* A negative result is valid here */
 
@@ -2406,6 +2308,8 @@ float8_covar_pop(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
 
        numerator = N * sumXY - sumX * sumY;
+       CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
+                                       isinf(sumY), true);
 
        PG_RETURN_FLOAT8(numerator / (N * N));
 }
@@ -2432,6 +2336,8 @@ float8_covar_samp(PG_FUNCTION_ARGS)
                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,8 +2370,12 @@ float8_corr(PG_FUNCTION_ARGS)
                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,8 +2411,12 @@ float8_regr_r2(PG_FUNCTION_ARGS)
                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,7 +2452,10 @@ float8_regr_slope(PG_FUNCTION_ARGS)
                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,7 +2487,10 @@ float8_regr_intercept(PG_FUNCTION_ARGS)
                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,7 +2518,7 @@ float48pl(PG_FUNCTION_ARGS)
        float8          result;
 
        result = arg1 + arg2;
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2610,7 +2530,7 @@ float48mi(PG_FUNCTION_ARGS)
        float8          result;
 
        result = arg1 - arg2;
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2622,7 +2542,8 @@ float48mul(PG_FUNCTION_ARGS)
        float8          result;
 
        result = arg1 * arg2;
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
+                                       arg1 == 0 || arg2 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2639,7 +2560,7 @@ float48div(PG_FUNCTION_ARGS)
                                 errmsg("division by zero")));
 
        result = arg1 / arg2;
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2658,7 +2579,7 @@ float84pl(PG_FUNCTION_ARGS)
 
        result = arg1 + arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2671,7 +2592,7 @@ float84mi(PG_FUNCTION_ARGS)
 
        result = arg1 - arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2684,7 +2605,8 @@ float84mul(PG_FUNCTION_ARGS)
 
        result = arg1 * arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
+                                       arg1 == 0 || arg2 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
@@ -2702,7 +2624,7 @@ float84div(PG_FUNCTION_ARGS)
 
        result = arg1 / arg2;
 
-       CheckFloat8Val(result);
+       CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
        PG_RETURN_FLOAT8(result);
 }
 
index 3970bda83d2c2c0600073dd07a867e6a1a469e12..194b96c720828c57f3fc73ecd465b8016e1a2765 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.75 2006/10/04 00:29:59 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.76 2007/01/02 20:00:49 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1124,6 +1124,11 @@ int4mod(PG_FUNCTION_ARGS)
                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 a696a6d1c5148a91c3e7cacaa66b8557bbef0917..fd8d0b319e9f75ac930d28a82a4f0e3154ef10db 100644 (file)
@@ -8,14 +8,14 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('     -34.84    ');
 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
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
+ERROR:  value out of range: overflow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
+ERROR:  value out of range: overflow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
+ERROR:  value out of range: underflow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
+ERROR:  value out of range: underflow
 -- bad input
 INSERT INTO FLOAT4_TBL(f1) VALUES ('');
 ERROR:  invalid input syntax for type real: ""
@@ -72,7 +72,11 @@ ERROR:  invalid input syntax for type real: "NaN x"
 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
+ ?column? 
+----------
+ Infinity
+(1 row)
+
 SELECT 'Infinity'::float4 / 'Infinity'::float4;
  ?column? 
 ----------
index b94816eaebd19ce85fd63e74bf5493febd55e359..b3bc431a156728a45d870ab55bd3acd9d512382b 100644 (file)
@@ -8,14 +8,14 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('     -34.84    ');
 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
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
+ERROR:  value out of range: overflow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
+ERROR:  value out of range: overflow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
+ERROR:  value out of range: underflow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
+ERROR:  value out of range: underflow
 -- bad input
 INSERT INTO FLOAT4_TBL(f1) VALUES ('');
 ERROR:  invalid input syntax for type real: ""
@@ -72,7 +72,11 @@ ERROR:  invalid input syntax for type real: "NaN x"
 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
+ ?column? 
+----------
+ Infinity
+(1 row)
+
 SELECT 'Infinity'::float4 / 'Infinity'::float4;
  ?column? 
 ----------
index 2bafa4b86c84d8a215f5ee6930dd26256ac72254..2aa7996200af48a23c81da98859287fff2ea9fee 100644 (file)
@@ -72,7 +72,11 @@ ERROR:  invalid input syntax for type double precision: "NaN x"
 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
+ ?column? 
+----------
+ Infinity
+(1 row)
+
 SELECT 'Infinity'::float8 / 'Infinity'::float8;
  ?column? 
 ----------
@@ -342,15 +346,15 @@ UPDATE FLOAT8_TBL
    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
+ERROR:  value out of range: overflow
 SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
-ERROR:  result is out of range
+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:  result is out of range
+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 71d9168950a91005219e1bbb12ce3e121ea90f84..83a78b299413abfca49c99cb962601f59fb88cb0 100644 (file)
@@ -80,7 +80,11 @@ ERROR:  invalid input syntax for type double precision: "NaN x"
 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
+ ?column? 
+----------
+ Infinity
+(1 row)
+
 SELECT 'Infinity'::float8 / 'Infinity'::float8;
  ?column? 
 ----------
@@ -350,15 +354,15 @@ UPDATE FLOAT8_TBL
    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
+ERROR:  value out of range: overflow
 SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
-ERROR:  result is out of range
+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:  result is out of range
+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 87db7d3d590babaa10422a6f6c203f279129786d..563b1a70b94392ff07d35b64a6de5a4830dd6ca2 100644 (file)
@@ -80,7 +80,11 @@ ERROR:  invalid input syntax for type double precision: "NaN x"
 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
+ ?column? 
+----------
+ Infinity
+(1 row)
+
 SELECT 'Infinity'::float8 / 'Infinity'::float8;
  ?column? 
 ----------
@@ -350,15 +354,15 @@ UPDATE FLOAT8_TBL
    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
+ERROR:  value out of range: overflow
 SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
-ERROR:  result is out of range
+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:  result is out of range
+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 8f5b32eac05820cdaaa155ef562b1a8c2ff7d8e0..38d2cbfb41778832779256696b53c7df7f898d65 100644 (file)
@@ -72,7 +72,11 @@ ERROR:  invalid input syntax for type double precision: "NaN x"
 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
+ ?column? 
+----------
+ Infinity
+(1 row)
+
 SELECT 'Infinity'::float8 / 'Infinity'::float8;
  ?column? 
 ----------
@@ -342,15 +346,15 @@ UPDATE FLOAT8_TBL
    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
+ERROR:  value out of range: overflow
 SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
-ERROR:  result is out of range
+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:  result is out of range
+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 a2140f547e5b3b6e561c659e9dbba32dbdce71f5..5944e2fc14902ba5bb7fb2f678a5acfc6392f39e 100644 (file)
@@ -11,10 +11,10 @@ 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');
-INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40');
-INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40');
-INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
 
 -- bad input
 INSERT INTO FLOAT4_TBL(f1) VALUES ('');