diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index a90d4db215..5885719850 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -1191,7 +1191,7 @@ dtof(PG_FUNCTION_ARGS) { float8 num = PG_GETARG_FLOAT8(0); - check_float4_val((float4) num, isinf(num), num == 0); + CHECKFLOATVAL((float4) num, isinf(num), num == 0); PG_RETURN_FLOAT4((float4) num); } @@ -1445,7 +1445,7 @@ dsqrt(PG_FUNCTION_ARGS) result = sqrt(arg1); - check_float8_val(result, isinf(arg1), arg1 == 0); + CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } @@ -1460,7 +1460,7 @@ dcbrt(PG_FUNCTION_ARGS) float8 result; result = cbrt(arg1); - check_float8_val(result, isinf(arg1), arg1 == 0); + CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } @@ -1532,7 +1532,7 @@ dpow(PG_FUNCTION_ARGS) else if (errno == ERANGE && result != 0 && !isinf(result)) result = get_float8_infinity(); - check_float8_val(result, isinf(arg1) || isinf(arg2), arg1 == 0); + CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT8(result); } @@ -1551,7 +1551,7 @@ dexp(PG_FUNCTION_ARGS) if (errno == ERANGE && result != 0 && !isinf(result)) result = get_float8_infinity(); - check_float8_val(result, isinf(arg1), false); + CHECKFLOATVAL(result, isinf(arg1), false); PG_RETURN_FLOAT8(result); } @@ -1580,7 +1580,7 @@ dlog1(PG_FUNCTION_ARGS) result = log(arg1); - check_float8_val(result, isinf(arg1), arg1 == 1); + CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result); } @@ -1610,7 +1610,7 @@ dlog10(PG_FUNCTION_ARGS) result = log10(arg1); - check_float8_val(result, isinf(arg1), arg1 == 1); + CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result); } @@ -1640,7 +1640,7 @@ dacos(PG_FUNCTION_ARGS) result = acos(arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1670,7 +1670,7 @@ dasin(PG_FUNCTION_ARGS) result = asin(arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1695,7 +1695,7 @@ datan(PG_FUNCTION_ARGS) */ result = atan(arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1720,7 +1720,7 @@ datan2(PG_FUNCTION_ARGS) */ result = atan2(arg1, arg2); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1760,7 +1760,7 @@ dcos(PG_FUNCTION_ARGS) (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1787,7 +1787,7 @@ dcot(PG_FUNCTION_ARGS) errmsg("input is out of range"))); result = 1.0 / result; - check_float8_val(result, true /* cot(0) == Inf */ , true); + CHECKFLOATVAL(result, true /* cot(0) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -1813,7 +1813,7 @@ dsin(PG_FUNCTION_ARGS) (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1839,7 +1839,7 @@ dtan(PG_FUNCTION_ARGS) (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); - check_float8_val(result, true /* tan(pi/2) == Inf */ , true); + CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -1991,7 +1991,7 @@ dacosd(PG_FUNCTION_ARGS) else result = 90.0 + asind_q1(-arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2026,7 +2026,7 @@ dasind(PG_FUNCTION_ARGS) else result = -asind_q1(-arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2056,7 +2056,7 @@ datand(PG_FUNCTION_ARGS) atan_arg1 = atan(arg1); result = (atan_arg1 / atan_1_0) * 45.0; - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2090,7 +2090,7 @@ datan2d(PG_FUNCTION_ARGS) atan2_arg1_arg2 = atan2(arg1, arg2); result = (atan2_arg1_arg2 / atan_1_0) * 45.0; - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2211,7 +2211,7 @@ dcosd(PG_FUNCTION_ARGS) result = sign * cosd_q1(arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2276,7 +2276,7 @@ dcotd(PG_FUNCTION_ARGS) if (result == 0.0) result = 0.0; - check_float8_val(result, true /* cotd(0) == Inf */ , true); + CHECKFLOATVAL(result, true /* cotd(0) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -2330,7 +2330,7 @@ dsind(PG_FUNCTION_ARGS) result = sign * sind_q1(arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2395,7 +2395,7 @@ dtand(PG_FUNCTION_ARGS) if (result == 0.0) result = 0.0; - check_float8_val(result, true /* tand(90) == Inf */ , true); + CHECKFLOATVAL(result, true /* tand(90) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -2462,7 +2462,7 @@ dsinh(PG_FUNCTION_ARGS) result = get_float8_infinity(); } - check_float8_val(result, true, true); + CHECKFLOATVAL(result, true, true); PG_RETURN_FLOAT8(result); } @@ -2486,7 +2486,7 @@ dcosh(PG_FUNCTION_ARGS) if (errno == ERANGE) result = get_float8_infinity(); - check_float8_val(result, true, false); + CHECKFLOATVAL(result, true, false); PG_RETURN_FLOAT8(result); } @@ -2504,7 +2504,7 @@ dtanh(PG_FUNCTION_ARGS) */ result = tanh(arg1); - check_float8_val(result, false, true); + CHECKFLOATVAL(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2522,7 +2522,7 @@ dasinh(PG_FUNCTION_ARGS) */ result = asinh(arg1); - check_float8_val(result, true, true); + CHECKFLOATVAL(result, true, true); PG_RETURN_FLOAT8(result); } @@ -2548,7 +2548,7 @@ dacosh(PG_FUNCTION_ARGS) result = acosh(arg1); - check_float8_val(result, true, true); + CHECKFLOATVAL(result, true, true); PG_RETURN_FLOAT8(result); } @@ -2583,7 +2583,7 @@ datanh(PG_FUNCTION_ARGS) else result = atanh(arg1); - check_float8_val(result, true, true); + CHECKFLOATVAL(result, true, true); PG_RETURN_FLOAT8(result); } @@ -2784,7 +2784,7 @@ float8_combine(PG_FUNCTION_ARGS) Sx = float8_pl(Sx1, Sx2); tmp = Sx1 / N1 - Sx2 / N2; Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp * tmp / N; - check_float8_val(Sxx, isinf(Sxx1) || isinf(Sxx2), true); + CHECKFLOATVAL(Sxx, isinf(Sxx1) || isinf(Sxx2), true); } /* @@ -3294,13 +3294,13 @@ float8_regr_combine(PG_FUNCTION_ARGS) Sx = float8_pl(Sx1, Sx2); tmp1 = Sx1 / N1 - Sx2 / N2; Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp1 * tmp1 / N; - check_float8_val(Sxx, isinf(Sxx1) || isinf(Sxx2), true); + CHECKFLOATVAL(Sxx, isinf(Sxx1) || isinf(Sxx2), true); Sy = float8_pl(Sy1, Sy2); tmp2 = Sy1 / N1 - Sy2 / N2; Syy = Syy1 + Syy2 + N1 * N2 * tmp2 * tmp2 / N; - check_float8_val(Syy, isinf(Syy1) || isinf(Syy2), true); + CHECKFLOATVAL(Syy, isinf(Syy1) || isinf(Syy2), true); Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N; - check_float8_val(Sxy, isinf(Sxy1) || isinf(Sxy2), true); + CHECKFLOATVAL(Sxy, isinf(Sxy1) || isinf(Sxy2), true); } /* diff --git a/src/include/utils/float.h b/src/include/utils/float.h index e2c5dc0f57..f692abab5b 100644 --- a/src/include/utils/float.h +++ b/src/include/utils/float.h @@ -32,6 +32,22 @@ static const uint32 nan[2] = {0xffffffff, 0x7fffffff}; #define NAN (*(const float8 *) nan) #endif +/* + * 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) + extern PGDLLIMPORT int extra_float_digits; /* @@ -130,6 +146,7 @@ get_float8_nan(void) /* * Checks to see if a float4/8 val has underflowed or overflowed + * Note: Deprecated; use CHECKFLOATVAL() macro instead! */ static inline void @@ -178,7 +195,7 @@ float4_pl(const float4 val1, const float4 val2) float4 result; result = val1 + val2; - check_float4_val(result, isinf(val1) || isinf(val2), true); + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), true); return result; } @@ -189,7 +206,7 @@ float8_pl(const float8 val1, const float8 val2) float8 result; result = val1 + val2; - check_float8_val(result, isinf(val1) || isinf(val2), true); + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), true); return result; } @@ -200,7 +217,7 @@ float4_mi(const float4 val1, const float4 val2) float4 result; result = val1 - val2; - check_float4_val(result, isinf(val1) || isinf(val2), true); + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), true); return result; } @@ -211,7 +228,7 @@ float8_mi(const float8 val1, const float8 val2) float8 result; result = val1 - val2; - check_float8_val(result, isinf(val1) || isinf(val2), true); + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), true); return result; } @@ -222,7 +239,7 @@ float4_mul(const float4 val1, const float4 val2) float4 result; result = val1 * val2; - check_float4_val(result, isinf(val1) || isinf(val2), + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), val1 == 0.0f || val2 == 0.0f); return result; @@ -234,7 +251,7 @@ float8_mul(const float8 val1, const float8 val2) float8 result; result = val1 * val2; - check_float8_val(result, isinf(val1) || isinf(val2), + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), val1 == 0.0 || val2 == 0.0); return result; @@ -251,7 +268,7 @@ float4_div(const float4 val1, const float4 val2) errmsg("division by zero"))); result = val1 / val2; - check_float4_val(result, isinf(val1) || isinf(val2), val1 == 0.0f); + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), val1 == 0.0f); return result; } @@ -267,7 +284,7 @@ float8_div(const float8 val1, const float8 val2) errmsg("division by zero"))); result = val1 / val2; - check_float8_val(result, isinf(val1) || isinf(val2), val1 == 0.0); + CHECKFLOATVAL(result, isinf(val1) || isinf(val2), val1 == 0.0); return result; }