📄 float.c
字号:
errno = 0; result = exp(arg1); if (errno == ERANGE && result != 0 && !isinf(result)) result = get_float8_infinity(); CHECKFLOATVAL(result, isinf(arg1), false); PG_RETURN_FLOAT8(result);}/* * dlog1 - returns the natural logarithm of arg1 */Datumdlog1(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; /* * Emit particular SQLSTATE error codes for ln(). This is required by the * SQL standard. */ if (arg1 == 0.0) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), errmsg("cannot take logarithm of zero"))); if (arg1 < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), errmsg("cannot take logarithm of a negative number"))); result = log(arg1); CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result);}/* * dlog10 - returns the base 10 logarithm of arg1 */Datumdlog10(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; /* * Emit particular SQLSTATE error codes for log(). The SQL spec doesn't * define log(), but it does define ln(), so it makes sense to emit the * same error code for an analogous error condition. */ if (arg1 == 0.0) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), errmsg("cannot take logarithm of zero"))); if (arg1 < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), errmsg("cannot take logarithm of a negative number"))); result = log10(arg1); CHECKFLOATVAL(result, isinf(arg1), arg1 == 1); PG_RETURN_FLOAT8(result);}/* * dacos - returns the arccos of arg1 (radians) */Datumdacos(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; /* * We use errno here because the trigonometric functions are cyclic and * hard to check for underflow. */ 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);}/* * dasin - returns the arcsin of arg1 (radians) */Datumdasin(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; 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);}/* * datan - returns the arctan of arg1 (radians) */Datumdatan(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; 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);}/* * atan2 - returns the arctan2 of arg1 (radians) */Datumdatan2(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); float8 result; 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);}/* * dcos - returns the cosine of arg1 (radians) */Datumdcos(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; 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);}/* * dcot - returns the cotangent of arg1 (radians) */Datumdcot(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; 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);}/* * dsin - returns the sine of arg1 (radians) */Datumdsin(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; 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);}/* * dtan - returns the tangent of arg1 (radians) */Datumdtan(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; errno = 0; result = tan(arg1); if (errno != 0) ereport(ERROR, (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);}/* * degrees - returns degrees converted from radians */Datumdegrees(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; result = arg1 * (180.0 / M_PI); CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result);}/* * dpi - returns the constant PI */Datumdpi(PG_FUNCTION_ARGS){ PG_RETURN_FLOAT8(M_PI);}/* * radians - returns radians converted from degrees */Datumradians(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; result = arg1 * (M_PI / 180.0); CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result);}/* * drandom - returns a random number */Datumdrandom(PG_FUNCTION_ARGS){ float8 result; /* result [0.0 - 1.0) */ result = (double) random() / ((double) MAX_RANDOM_VALUE + 1); PG_RETURN_FLOAT8(result);}/* * setseed - set seed for the random number generator */Datumsetseed(PG_FUNCTION_ARGS){ float8 seed = PG_GETARG_FLOAT8(0); int iseed = (int) (seed * MAX_RANDOM_VALUE); srandom((unsigned int) iseed); PG_RETURN_VOID();}/* * ========================= * FLOAT AGGREGATE OPERATORS * ========================= * * float8_accum - accumulate for AVG(), variance aggregates, etc. * float4_accum - same, but input data is float4 * float8_avg - produce final result for float AVG() * float8_var_samp - produce final result for float VAR_SAMP() * float8_var_pop - produce final result for float VAR_POP() * float8_stddev_samp - produce final result for float STDDEV_SAMP() * float8_stddev_pop - produce final result for float STDDEV_POP() * * The transition datatype for all these aggregates is a 3-element array * of float8, holding the values N, sum(X), sum(X*X) in that order. * * Note that we represent N as a float to avoid having to build a special * datatype. Given a reasonable floating-point implementation, there should * be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the * user will have doubtless lost interest anyway...) */static float8 *check_float8_array(ArrayType *transarray, const char *caller, int n){ /* * We expect the input to be an N-element float array; verify that. We * don't need to use deconstruct_array() since the array data is just * going to look like a C array of N float8 values. */ if (ARR_NDIM(transarray) != 1 || ARR_DIMS(transarray)[0] != n || ARR_HASNULL(transarray) || ARR_ELEMTYPE(transarray) != FLOAT8OID) elog(ERROR, "%s: expected %d-element float8 array", caller, n); return (float8 *) ARR_DATA_PTR(transarray);}Datumfloat8_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 by nodeAgg, we can cheat and modify our first * parameter in-place to reduce palloc overhead. Otherwise we construct a * new array with the updated transition data and return it. */ if (fcinfo->context && IsA(fcinfo->context, AggState)) { transvalues[0] = N; transvalues[1] = sumX; transvalues[2] = sumX2; PG_RETURN_ARRAYTYPE_P(transarray); } else { Datum transdatums[3]; ArrayType *result; transdatums[0] = Float8GetDatumFast(N); transdatums[1] = Float8GetDatumFast(sumX); transdatums[2] = Float8GetDatumFast(sumX2); result = construct_array(transdatums, 3, FLOAT8OID, sizeof(float8), false /* float8 byval */ , 'd'); PG_RETURN_ARRAYTYPE_P(result); }}Datumfloat4_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 * new array with the updated transition data and return it. */ if (fcinfo->context && IsA(fcinfo->context, AggState)) { transvalues[0] = N; transvalues[1] = sumX; transvalues[2] = sumX2; PG_RETURN_ARRAYTYPE_P(transarray); } else { Datum transdatums[3]; ArrayType *result; transdatums[0] = Float8GetDatumFast(N); transdatums[1] = Float8GetDatumFast(sumX); transdatums[2] = Float8GetDatumFast(sumX2); result = construct_array(transdatums, 3, FLOAT8OID, sizeof(float8), false /* float8 byval */ , 'd'); PG_RETURN_ARRAYTYPE_P(result); }}Datumfloat8_avg(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 *transvalues; float8 N, sumX; transvalues = check_float8_array(transarray, "float8_avg", 3); N = transvalues[0]; sumX = transvalues[1]; /* ignore sumX2 */ /* SQL92 defines AVG of no values to be NULL */ if (N == 0.0) PG_RETURN_NULL(); PG_RETURN_FLOAT8(sumX / N);}Datumfloat8_var_pop(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 *transvalues; float8 N, sumX, sumX2, numerator; transvalues = check_float8_array(transarray, "float8_var_pop", 3); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; /* Population variance is undefined when N is 0, so return NULL */ if (N == 0.0) 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) PG_RETURN_FLOAT8(0.0); PG_RETURN_FLOAT8(numerator / (N * N));}Datumfloat8_var_samp(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 *transvalues; float8 N, sumX, sumX2, numerator; transvalues = check_float8_array(transarray, "float8_var_samp", 3); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; /* Sample variance is undefined when N is 0 or 1, so return NULL */ if (N <= 1.0) 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) PG_RETURN_FLOAT8(0.0); PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));}Datumfloat8_stddev_pop(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 *transvalues; float8 N, sumX, sumX2, numerator; transvalues = check_float8_array(transarray, "float8_stddev_pop", 3); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; /* Population stddev is undefined when N is 0, so return NULL */ if (N == 0.0) 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) PG_RETURN_FLOAT8(0.0); PG_RETURN_FLOAT8(sqrt(numerator / (N * N)));}Datumfloat8_stddev_samp(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 *transvalues; float8 N, sumX, sumX2, numerator; transvalues = check_float8_array(transarray, "float8_stddev_samp", 3); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; /* Sample stddev is undefined when N is 0 or 1, so return NULL */ if (N <= 1.0) 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) PG_RETURN_FLOAT8(0.0); PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));}/* * ========================= * SQL2003 BINARY AGGREGATES * ========================= * * The transition datatype for all these aggregates is a 6-element array of * float8, holding the values N, sum(X), sum(X*X), sum(Y), sum(Y*Y), sum(X*Y) * in that order. Note that Y is the first argument to the aggregates! * * It might seem attractive to optimize this by having multiple accumulator * functions that only calculate the sums actually needed. But on most * modern machines, a couple of extra floating-point multiplies will be * insignificant compared to the other per-tuple overhead, so I've chosen * to minimize code space instead. */Datumfloat8_regr_accum(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 newvalY = PG_GETARG_FLOAT8(1); float8 newvalX = PG_GETARG_FLOAT8(2); float8 *transvalues; float8 N, sumX, sumX2, sumY, sumY2, sumXY; transvalues = check_float8_array(transarray, "float8_regr_accum", 6); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; sumY = transvalues[3]; sumY2 = transvalues[4]; sumXY = transvalues[5]; 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 * new array with the updated transition data and return it. */ if (fcinfo->context && IsA(fcinfo->context, AggState)) { transvalues[0] = N; transvalues[1] = sumX; transvalues[2] = sumX2; transvalues[3] = sumY; transvalues[4] = sumY2; transvalues[5] = sumXY; PG_RETURN_ARRAYTYPE_P(transarray); } else { Datum transdatums[6]; ArrayType *result; transdatums[0] = Float8GetDatumFast(N); transdatums[1] = Float8GetDatumFast(sumX); transdatums[2] = Float8GetDatumFast(sumX2); transdatums[3] = Float8GetDatumFast(sumY); transdatums[4] = Float8GetDatumFast(sumY2); transdatums[5] = Float8GetDatumFast(sumXY); result = construct_array(transdatums, 6, FLOAT8OID, sizeof(float8), false /* float8 byval */ , 'd'); PG_RETURN_ARRAYTYPE_P(result); }}Datumfloat8_regr_sxx(PG_FUNCTION_ARGS){ ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float8 *transvalues; float8 N,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -