diff options
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r-- | src/backend/utils/adt/float.c | 589 |
1 files changed, 135 insertions, 454 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index b86205b0987..df35557b737 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -23,44 +23,11 @@ #include "common/int.h" #include "libpq/pqformat.h" #include "utils/array.h" -#include "utils/builtins.h" +#include "utils/float.h" +#include "utils/fmgrprotos.h" #include "utils/sortsupport.h" -#ifndef M_PI -/* from my RH5.2 gcc math.h file - thomas 2000-04-03 */ -#define M_PI 3.14159265358979323846 -#endif - -/* Radians per degree, a.k.a. PI / 180 */ -#define RADIANS_PER_DEGREE 0.0174532925199432957692 - -/* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. NAN definition from - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrfNotNumberNANItems.asp - */ -#if defined(WIN32) && !defined(NAN) -static const uint32 nan[2] = {0xffffffff, 0x7fffffff}; - -#define NAN (*(const double *) 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) - - /* Configurable GUC parameter */ int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */ @@ -106,86 +73,6 @@ static double cbrt(double x); /* - * Routines to provide reasonably platform-independent handling of - * infinity and NaN. We assume that isinf() and isnan() are available - * and work per spec. (On some platforms, we have to supply our own; - * see src/port.) However, generating an Infinity or NaN in the first - * place is less well standardized; pre-C99 systems tend not to have C99's - * INFINITY and NAN macros. We centralize our workarounds for this here. - */ - -double -get_float8_infinity(void) -{ -#ifdef INFINITY - /* C99 standard way */ - return (double) INFINITY; -#else - - /* - * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the - * largest normal double. We assume forcing an overflow will get us a - * true infinity. - */ - return (double) (HUGE_VAL * HUGE_VAL); -#endif -} - -/* -* The funny placements of the two #pragmas is necessary because of a -* long lived bug in the Microsoft compilers. -* See http://support.microsoft.com/kb/120968/en-us for details -*/ -#if (_MSC_VER >= 1800) -#pragma warning(disable:4756) -#endif -float -get_float4_infinity(void) -{ -#ifdef INFINITY - /* C99 standard way */ - return (float) INFINITY; -#else -#if (_MSC_VER >= 1800) -#pragma warning(default:4756) -#endif - - /* - * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the - * largest normal double. We assume forcing an overflow will get us a - * true infinity. - */ - return (float) (HUGE_VAL * HUGE_VAL); -#endif -} - -double -get_float8_nan(void) -{ - /* (double) NAN doesn't work on some NetBSD/MIPS releases */ -#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__)) - /* C99 standard way */ - return (double) NAN; -#else - /* Assume we can get a NAN via zero divide */ - return (double) (0.0 / 0.0); -#endif -} - -float -get_float4_nan(void) -{ -#ifdef NAN - /* C99 standard way */ - return (float) NAN; -#else - /* Assume we can get a NAN via zero divide */ - return (float) (0.0 / 0.0); -#endif -} - - -/* * Returns -1 if 'val' represents negative infinity, 1 if 'val' * represents (positive) infinity, and 0 otherwise. On some platforms, * this is equivalent to the isinf() macro, but not everywhere: C99 @@ -343,7 +230,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 */ - CHECKFLOATVAL((float4) val, isinf(val), val == 0); + check_float4_val((float4) val, isinf(val), val == 0); PG_RETURN_FLOAT4((float4) val); } @@ -693,7 +580,7 @@ float4larger(PG_FUNCTION_ARGS) float4 arg2 = PG_GETARG_FLOAT4(1); float4 result; - if (float4_cmp_internal(arg1, arg2) > 0) + if (float4_gt(arg1, arg2)) result = arg1; else result = arg2; @@ -707,7 +594,7 @@ float4smaller(PG_FUNCTION_ARGS) float4 arg2 = PG_GETARG_FLOAT4(1); float4 result; - if (float4_cmp_internal(arg1, arg2) < 0) + if (float4_lt(arg1, arg2)) result = arg1; else result = arg2; @@ -760,7 +647,7 @@ float8larger(PG_FUNCTION_ARGS) float8 arg2 = PG_GETARG_FLOAT8(1); float8 result; - if (float8_cmp_internal(arg1, arg2) > 0) + if (float8_gt(arg1, arg2)) result = arg1; else result = arg2; @@ -774,7 +661,7 @@ float8smaller(PG_FUNCTION_ARGS) float8 arg2 = PG_GETARG_FLOAT8(1); float8 result; - if (float8_cmp_internal(arg1, arg2) < 0) + if (float8_lt(arg1, arg2)) result = arg1; else result = arg2; @@ -799,19 +686,8 @@ float4pl(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - float4 result; - - result = arg1 + arg2; - /* - * There isn't any way to check for underflow of addition/subtraction - * because numbers near the underflow value have already been rounded to - * the point where we can't detect 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); + PG_RETURN_FLOAT4(float4_pl(arg1, arg2)); } Datum @@ -819,11 +695,8 @@ float4mi(PG_FUNCTION_ARGS) { 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); + PG_RETURN_FLOAT4(float4_mi(arg1, arg2)); } Datum @@ -831,12 +704,8 @@ float4mul(PG_FUNCTION_ARGS) { 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); + PG_RETURN_FLOAT4(float4_mul(arg1, arg2)); } Datum @@ -844,17 +713,8 @@ float4div(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - float4 result; - - if (arg2 == 0.0) - ereport(ERROR, - (errcode(ERRCODE_DIVISION_BY_ZERO), - errmsg("division by zero"))); - result = arg1 / arg2; - - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); - PG_RETURN_FLOAT4(result); + PG_RETURN_FLOAT4(float4_div(arg1, arg2)); } /* @@ -868,12 +728,8 @@ float8pl(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - - result = arg1 + arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_pl(arg1, arg2)); } Datum @@ -881,12 +737,8 @@ float8mi(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - - result = arg1 - arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mi(arg1, arg2)); } Datum @@ -894,13 +746,8 @@ float8mul(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - - result = arg1 * arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), - arg1 == 0 || arg2 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mul(arg1, arg2)); } Datum @@ -908,17 +755,8 @@ float8div(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - if (arg2 == 0.0) - ereport(ERROR, - (errcode(ERRCODE_DIVISION_BY_ZERO), - errmsg("division by zero"))); - - result = arg1 / arg2; - - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_div(arg1, arg2)); } @@ -934,31 +772,11 @@ float8div(PG_FUNCTION_ARGS) int float4_cmp_internal(float4 a, float4 b) { - /* - * We consider all NANs to be equal and larger than any non-NAN. This is - * somewhat arbitrary; the important thing is to have a consistent sort - * order. - */ - if (isnan(a)) - { - if (isnan(b)) - return 0; /* NAN = NAN */ - else - return 1; /* NAN > non-NAN */ - } - else if (isnan(b)) - { - return -1; /* non-NAN < NAN */ - } - else - { - if (a > b) - return 1; - else if (a < b) - return -1; - else - return 0; - } + if (float4_gt(a, b)) + return 1; + if (float4_lt(a, b)) + return -1; + return 0; } Datum @@ -967,7 +785,7 @@ float4eq(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0); + PG_RETURN_BOOL(float4_eq(arg1, arg2)); } Datum @@ -976,7 +794,7 @@ float4ne(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0); + PG_RETURN_BOOL(float4_ne(arg1, arg2)); } Datum @@ -985,7 +803,7 @@ float4lt(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0); + PG_RETURN_BOOL(float4_lt(arg1, arg2)); } Datum @@ -994,7 +812,7 @@ float4le(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0); + PG_RETURN_BOOL(float4_le(arg1, arg2)); } Datum @@ -1003,7 +821,7 @@ float4gt(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0); + PG_RETURN_BOOL(float4_gt(arg1, arg2)); } Datum @@ -1012,7 +830,7 @@ float4ge(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0); + PG_RETURN_BOOL(float4_ge(arg1, arg2)); } Datum @@ -1048,31 +866,11 @@ btfloat4sortsupport(PG_FUNCTION_ARGS) int float8_cmp_internal(float8 a, float8 b) { - /* - * We consider all NANs to be equal and larger than any non-NAN. This is - * somewhat arbitrary; the important thing is to have a consistent sort - * order. - */ - if (isnan(a)) - { - if (isnan(b)) - return 0; /* NAN = NAN */ - else - return 1; /* NAN > non-NAN */ - } - else if (isnan(b)) - { - return -1; /* non-NAN < NAN */ - } - else - { - if (a > b) - return 1; - else if (a < b) - return -1; - else - return 0; - } + if (float8_gt(a, b)) + return 1; + if (float8_lt(a, b)) + return -1; + return 0; } Datum @@ -1081,7 +879,7 @@ float8eq(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0); + PG_RETURN_BOOL(float8_eq(arg1, arg2)); } Datum @@ -1090,7 +888,7 @@ float8ne(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0); + PG_RETURN_BOOL(float8_ne(arg1, arg2)); } Datum @@ -1099,7 +897,7 @@ float8lt(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0); + PG_RETURN_BOOL(float8_lt(arg1, arg2)); } Datum @@ -1108,7 +906,7 @@ float8le(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0); + PG_RETURN_BOOL(float8_le(arg1, arg2)); } Datum @@ -1117,7 +915,7 @@ float8gt(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0); + PG_RETURN_BOOL(float8_gt(arg1, arg2)); } Datum @@ -1126,7 +924,7 @@ float8ge(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0); + PG_RETURN_BOOL(float8_ge(arg1, arg2)); } Datum @@ -1341,7 +1139,7 @@ dtof(PG_FUNCTION_ARGS) { float8 num = PG_GETARG_FLOAT8(0); - CHECKFLOATVAL((float4) num, isinf(num), num == 0); + check_float4_val((float4) num, isinf(num), num == 0); PG_RETURN_FLOAT4((float4) num); } @@ -1566,7 +1364,7 @@ dsqrt(PG_FUNCTION_ARGS) result = sqrt(arg1); - CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); + check_float8_val(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } @@ -1581,7 +1379,7 @@ dcbrt(PG_FUNCTION_ARGS) float8 result; result = cbrt(arg1); - CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); + check_float8_val(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result); } @@ -1653,7 +1451,7 @@ dpow(PG_FUNCTION_ARGS) else if (errno == ERANGE && result != 0 && !isinf(result)) result = get_float8_infinity(); - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); + check_float8_val(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT8(result); } @@ -1672,7 +1470,7 @@ dexp(PG_FUNCTION_ARGS) if (errno == ERANGE && result != 0 && !isinf(result)) result = get_float8_infinity(); - CHECKFLOATVAL(result, isinf(arg1), false); + check_float8_val(result, isinf(arg1), false); PG_RETURN_FLOAT8(result); } @@ -1701,7 +1499,7 @@ dlog1(PG_FUNCTION_ARGS) result = log(arg1); - CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); + check_float8_val(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result); } @@ -1731,7 +1529,7 @@ dlog10(PG_FUNCTION_ARGS) result = log10(arg1); - CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); + check_float8_val(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result); } @@ -1761,7 +1559,7 @@ dacos(PG_FUNCTION_ARGS) result = acos(arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1791,7 +1589,7 @@ dasin(PG_FUNCTION_ARGS) result = asin(arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1816,7 +1614,7 @@ datan(PG_FUNCTION_ARGS) */ result = atan(arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1841,7 +1639,7 @@ datan2(PG_FUNCTION_ARGS) */ result = atan2(arg1, arg2); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1881,7 +1679,7 @@ dcos(PG_FUNCTION_ARGS) (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1908,7 +1706,7 @@ dcot(PG_FUNCTION_ARGS) errmsg("input is out of range"))); result = 1.0 / result; - CHECKFLOATVAL(result, true /* cot(0) == Inf */ , true); + check_float8_val(result, true /* cot(0) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -1934,7 +1732,7 @@ dsin(PG_FUNCTION_ARGS) (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -1960,7 +1758,7 @@ dtan(PG_FUNCTION_ARGS) (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range"))); - CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */ , true); + check_float8_val(result, true /* tan(pi/2) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -2112,7 +1910,7 @@ dacosd(PG_FUNCTION_ARGS) else result = 90.0 + asind_q1(-arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2147,7 +1945,7 @@ dasind(PG_FUNCTION_ARGS) else result = -asind_q1(-arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2177,7 +1975,7 @@ datand(PG_FUNCTION_ARGS) atan_arg1 = atan(arg1); result = (atan_arg1 / atan_1_0) * 45.0; - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2211,7 +2009,7 @@ datan2d(PG_FUNCTION_ARGS) atan2_arg1_arg2 = atan2(arg1, arg2); result = (atan2_arg1_arg2 / atan_1_0) * 45.0; - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2332,7 +2130,7 @@ dcosd(PG_FUNCTION_ARGS) result = sign * cosd_q1(arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2397,7 +2195,7 @@ dcotd(PG_FUNCTION_ARGS) if (result == 0.0) result = 0.0; - CHECKFLOATVAL(result, true /* cotd(0) == Inf */ , true); + check_float8_val(result, true /* cotd(0) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -2451,7 +2249,7 @@ dsind(PG_FUNCTION_ARGS) result = sign * sind_q1(arg1); - CHECKFLOATVAL(result, false, true); + check_float8_val(result, false, true); PG_RETURN_FLOAT8(result); } @@ -2516,7 +2314,7 @@ dtand(PG_FUNCTION_ARGS) if (result == 0.0) result = 0.0; - CHECKFLOATVAL(result, true /* tand(90) == Inf */ , true); + check_float8_val(result, true /* tand(90) == Inf */ , true); PG_RETURN_FLOAT8(result); } @@ -2528,12 +2326,8 @@ Datum degrees(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); - float8 result; - - result = arg1 / RADIANS_PER_DEGREE; - CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_div(arg1, RADIANS_PER_DEGREE)); } @@ -2554,12 +2348,8 @@ Datum radians(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); - float8 result; - result = arg1 * RADIANS_PER_DEGREE; - - CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mul(arg1, RADIANS_PER_DEGREE)); } @@ -2651,31 +2441,16 @@ float8_combine(PG_FUNCTION_ARGS) ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1); float8 *transvalues1; float8 *transvalues2; - float8 N, - sumX, - sumX2; if (!AggCheckCallContext(fcinfo, NULL)) elog(ERROR, "aggregate function called in non-aggregate context"); transvalues1 = check_float8_array(transarray1, "float8_combine", 3); - N = transvalues1[0]; - sumX = transvalues1[1]; - sumX2 = transvalues1[2]; - transvalues2 = check_float8_array(transarray2, "float8_combine", 3); - N += transvalues2[0]; - sumX += transvalues2[1]; - CHECKFLOATVAL(sumX, isinf(transvalues1[1]) || isinf(transvalues2[1]), - true); - sumX2 += transvalues2[2]; - CHECKFLOATVAL(sumX2, isinf(transvalues1[2]) || isinf(transvalues2[2]), - true); - - transvalues1[0] = N; - transvalues1[1] = sumX; - transvalues1[2] = sumX2; + transvalues1[0] = transvalues1[0] + transvalues2[0]; + transvalues1[1] = float8_pl(transvalues1[1], transvalues2[1]); + transvalues1[2] = float8_pl(transvalues1[2], transvalues2[2]); PG_RETURN_ARRAYTYPE_P(transarray1); } @@ -2686,20 +2461,8 @@ float8_accum(PG_FUNCTION_ARGS) ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 newval = PG_GETARG_FLOAT8(1); float8 *transvalues; - float8 N, - sumX, - sumX2; transvalues = check_float8_array(transarray, "float8_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 as an aggregate, we can cheat and modify our first @@ -2708,9 +2471,9 @@ float8_accum(PG_FUNCTION_ARGS) */ if (AggCheckCallContext(fcinfo, NULL)) { - transvalues[0] = N; - transvalues[1] = sumX; - transvalues[2] = sumX2; + transvalues[0] = transvalues[0] + 1.0; + transvalues[1] = float8_pl(transvalues[1], newval); + transvalues[2] = float8_pl(transvalues[2], float8_mul(newval, newval)); PG_RETURN_ARRAYTYPE_P(transarray); } @@ -2719,9 +2482,9 @@ float8_accum(PG_FUNCTION_ARGS) Datum transdatums[3]; ArrayType *result; - transdatums[0] = Float8GetDatumFast(N); - transdatums[1] = Float8GetDatumFast(sumX); - transdatums[2] = Float8GetDatumFast(sumX2); + transvalues[0] = transvalues[0] + 1.0; + transvalues[1] = float8_pl(transvalues[1], newval); + transvalues[2] = float8_pl(transvalues[2], float8_mul(newval, newval)); result = construct_array(transdatums, 3, FLOAT8OID, @@ -2739,20 +2502,8 @@ float4_accum(PG_FUNCTION_ARGS) /* 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 as an aggregate, we can cheat and modify our first @@ -2761,9 +2512,9 @@ float4_accum(PG_FUNCTION_ARGS) */ if (AggCheckCallContext(fcinfo, NULL)) { - transvalues[0] = N; - transvalues[1] = sumX; - transvalues[2] = sumX2; + transvalues[0] = transvalues[0] + 1.0; + transvalues[1] = float8_pl(transvalues[1], newval); + transvalues[2] = float8_pl(transvalues[2], float8_mul(newval, newval)); PG_RETURN_ARRAYTYPE_P(transarray); } @@ -2772,9 +2523,9 @@ float4_accum(PG_FUNCTION_ARGS) Datum transdatums[3]; ArrayType *result; - transdatums[0] = Float8GetDatumFast(N); - transdatums[1] = Float8GetDatumFast(sumX); - transdatums[2] = Float8GetDatumFast(sumX2); + transvalues[0] = transvalues[0] + 1.0; + transvalues[1] = float8_pl(transvalues[1], newval); + transvalues[2] = float8_pl(transvalues[2], float8_mul(newval, newval)); result = construct_array(transdatums, 3, FLOAT8OID, @@ -2824,7 +2575,7 @@ float8_var_pop(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) @@ -2853,7 +2604,7 @@ float8_var_samp(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) @@ -2882,7 +2633,7 @@ float8_stddev_pop(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) @@ -2911,7 +2662,7 @@ float8_stddev_samp(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) @@ -2960,16 +2711,16 @@ float8_regr_accum(PG_FUNCTION_ARGS) N += 1.0; sumX += newvalX; - CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newvalX), true); + check_float8_val(sumX, isinf(transvalues[1]) || isinf(newvalX), true); sumX2 += newvalX * newvalX; - CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newvalX), true); + check_float8_val(sumX2, isinf(transvalues[2]) || isinf(newvalX), true); sumY += newvalY; - CHECKFLOATVAL(sumY, isinf(transvalues[3]) || isinf(newvalY), true); + check_float8_val(sumY, isinf(transvalues[3]) || isinf(newvalY), true); sumY2 += newvalY * newvalY; - CHECKFLOATVAL(sumY2, isinf(transvalues[4]) || isinf(newvalY), true); + check_float8_val(sumY2, isinf(transvalues[4]) || isinf(newvalY), true); sumXY += newvalX * newvalY; - CHECKFLOATVAL(sumXY, isinf(transvalues[5]) || isinf(newvalX) || - isinf(newvalY), true); + check_float8_val(sumXY, isinf(transvalues[5]) || isinf(newvalX) || + isinf(newvalY), true); /* * If we're invoked as an aggregate, we can cheat and modify our first @@ -3022,49 +2773,19 @@ float8_regr_combine(PG_FUNCTION_ARGS) ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1); float8 *transvalues1; float8 *transvalues2; - float8 N, - sumX, - sumX2, - sumY, - sumY2, - sumXY; if (!AggCheckCallContext(fcinfo, NULL)) elog(ERROR, "aggregate function called in non-aggregate context"); transvalues1 = check_float8_array(transarray1, "float8_regr_combine", 6); - N = transvalues1[0]; - sumX = transvalues1[1]; - sumX2 = transvalues1[2]; - sumY = transvalues1[3]; - sumY2 = transvalues1[4]; - sumXY = transvalues1[5]; - transvalues2 = check_float8_array(transarray2, "float8_regr_combine", 6); - N += transvalues2[0]; - sumX += transvalues2[1]; - CHECKFLOATVAL(sumX, isinf(transvalues1[1]) || isinf(transvalues2[1]), - true); - sumX2 += transvalues2[2]; - CHECKFLOATVAL(sumX2, isinf(transvalues1[2]) || isinf(transvalues2[2]), - true); - sumY += transvalues2[3]; - CHECKFLOATVAL(sumY, isinf(transvalues1[3]) || isinf(transvalues2[3]), - true); - sumY2 += transvalues2[4]; - CHECKFLOATVAL(sumY2, isinf(transvalues1[4]) || isinf(transvalues2[4]), - true); - sumXY += transvalues2[5]; - CHECKFLOATVAL(sumXY, isinf(transvalues1[5]) || isinf(transvalues2[5]), - true); - - transvalues1[0] = N; - transvalues1[1] = sumX; - transvalues1[2] = sumX2; - transvalues1[3] = sumY; - transvalues1[4] = sumY2; - transvalues1[5] = sumXY; + transvalues1[0] = transvalues1[0] + transvalues2[0]; + transvalues1[1] = float8_pl(transvalues1[1], transvalues2[1]); + transvalues1[2] = float8_pl(transvalues1[2], transvalues2[2]); + transvalues1[3] = float8_pl(transvalues1[3], transvalues2[3]); + transvalues1[4] = float8_pl(transvalues1[4], transvalues2[4]); + transvalues1[5] = float8_pl(transvalues1[5], transvalues2[5]); PG_RETURN_ARRAYTYPE_P(transarray1); } @@ -3090,7 +2811,7 @@ float8_regr_sxx(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numerator, isinf(sumX2) || isinf(sumX), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) @@ -3119,7 +2840,7 @@ float8_regr_syy(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumY2 - sumY * sumY; - CHECKFLOATVAL(numerator, isinf(sumY2) || isinf(sumY), true); + check_float8_val(numerator, isinf(sumY2) || isinf(sumY), true); /* Watch out for roundoff error producing a negative numerator */ if (numerator <= 0.0) @@ -3150,8 +2871,8 @@ float8_regr_sxy(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumXY - sumX * sumY; - CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) || - isinf(sumY), true); + check_float8_val(numerator, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); /* A negative result is valid here */ @@ -3218,8 +2939,8 @@ float8_covar_pop(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumXY - sumX * sumY; - CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) || - isinf(sumY), true); + check_float8_val(numerator, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); PG_RETURN_FLOAT8(numerator / (N * N)); } @@ -3246,8 +2967,8 @@ float8_covar_samp(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numerator = N * sumXY - sumX * sumY; - CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) || - isinf(sumY), true); + check_float8_val(numerator, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); PG_RETURN_FLOAT8(numerator / (N * (N - 1.0))); } @@ -3280,12 +3001,12 @@ float8_corr(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorY = N * sumY2 - sumY * sumY; - CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true); + check_float8_val(numeratorY, isinf(sumY2) || isinf(sumY), true); numeratorXY = N * sumXY - sumX * sumY; - CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) || - isinf(sumY), true); + check_float8_val(numeratorXY, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); if (numeratorX <= 0 || numeratorY <= 0) PG_RETURN_NULL(); @@ -3320,12 +3041,12 @@ float8_regr_r2(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorY = N * sumY2 - sumY * sumY; - CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true); + check_float8_val(numeratorY, isinf(sumY2) || isinf(sumY), true); numeratorXY = N * sumXY - sumX * sumY; - CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) || - isinf(sumY), true); + check_float8_val(numeratorXY, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); if (numeratorX <= 0) PG_RETURN_NULL(); /* per spec, horizontal line produces 1.0 */ @@ -3361,10 +3082,10 @@ float8_regr_slope(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorXY = N * sumXY - sumX * sumY; - CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) || - isinf(sumY), true); + check_float8_val(numeratorXY, isinf(sumXY) || isinf(sumX) || + isinf(sumY), true); if (numeratorX <= 0) PG_RETURN_NULL(); @@ -3396,10 +3117,10 @@ float8_regr_intercept(PG_FUNCTION_ARGS) PG_RETURN_NULL(); numeratorX = N * sumX2 - sumX * sumX; - CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true); + check_float8_val(numeratorX, isinf(sumX2) || isinf(sumX), true); numeratorXXY = sumY * sumX2 - sumX * sumXY; - CHECKFLOATVAL(numeratorXXY, isinf(sumY) || isinf(sumX2) || - isinf(sumX) || isinf(sumXY), true); + check_float8_val(numeratorXXY, isinf(sumY) || isinf(sumX2) || + isinf(sumX) || isinf(sumXY), true); if (numeratorX <= 0) PG_RETURN_NULL(); @@ -3424,11 +3145,8 @@ float48pl(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - result = arg1 + arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_pl((float8) arg1, arg2)); } Datum @@ -3436,11 +3154,8 @@ float48mi(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - result = arg1 - arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mi((float8) arg1, arg2)); } Datum @@ -3448,12 +3163,8 @@ float48mul(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - result = arg1 * arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), - arg1 == 0 || arg2 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mul((float8) arg1, arg2)); } Datum @@ -3461,16 +3172,8 @@ float48div(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - float8 result; - if (arg2 == 0.0) - ereport(ERROR, - (errcode(ERRCODE_DIVISION_BY_ZERO), - errmsg("division by zero"))); - - result = arg1 / arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_div((float8) arg1, arg2)); } /* @@ -3484,12 +3187,8 @@ float84pl(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - float8 result; - - result = arg1 + arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_pl(arg1, (float8) arg2)); } Datum @@ -3497,12 +3196,8 @@ float84mi(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - float8 result; - - result = arg1 - arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mi(arg1, (float8) arg2)); } Datum @@ -3510,13 +3205,8 @@ float84mul(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - float8 result; - - result = arg1 * arg2; - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), - arg1 == 0 || arg2 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_mul(arg1, (float8) arg2)); } Datum @@ -3524,17 +3214,8 @@ float84div(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - float8 result; - if (arg2 == 0.0) - ereport(ERROR, - (errcode(ERRCODE_DIVISION_BY_ZERO), - errmsg("division by zero"))); - - result = arg1 / arg2; - - CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); - PG_RETURN_FLOAT8(result); + PG_RETURN_FLOAT8(float8_div(arg1, (float8) arg2)); } /* @@ -3552,7 +3233,7 @@ float48eq(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0); + PG_RETURN_BOOL(float8_eq((float8) arg1, arg2)); } Datum @@ -3561,7 +3242,7 @@ float48ne(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0); + PG_RETURN_BOOL(float8_ne((float8) arg1, arg2)); } Datum @@ -3570,7 +3251,7 @@ float48lt(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0); + PG_RETURN_BOOL(float8_lt((float8) arg1, arg2)); } Datum @@ -3579,7 +3260,7 @@ float48le(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0); + PG_RETURN_BOOL(float8_le((float8) arg1, arg2)); } Datum @@ -3588,7 +3269,7 @@ float48gt(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0); + PG_RETURN_BOOL(float8_gt((float8) arg1, arg2)); } Datum @@ -3597,7 +3278,7 @@ float48ge(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0); + PG_RETURN_BOOL(float8_ge((float8) arg1, arg2)); } /* @@ -3609,7 +3290,7 @@ float84eq(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0); + PG_RETURN_BOOL(float8_eq(arg1, (float8) arg2)); } Datum @@ -3618,7 +3299,7 @@ float84ne(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0); + PG_RETURN_BOOL(float8_ne(arg1, (float8) arg2)); } Datum @@ -3627,7 +3308,7 @@ float84lt(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0); + PG_RETURN_BOOL(float8_lt(arg1, (float8) arg2)); } Datum @@ -3636,7 +3317,7 @@ float84le(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0); + PG_RETURN_BOOL(float8_le(arg1, (float8) arg2)); } Datum @@ -3645,7 +3326,7 @@ float84gt(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0); + PG_RETURN_BOOL(float8_gt(arg1, (float8) arg2)); } Datum @@ -3654,7 +3335,7 @@ float84ge(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); - PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0); + PG_RETURN_BOOL(float8_ge(arg1, (float8) arg2)); } /* |