📄 float.c
字号:
/* * ==================== * ARITHMETIC OPERATORS * ==================== *//* * float4pl - returns arg1 + arg2 * float4mi - returns arg1 - arg2 * float4mul - returns arg1 * arg2 * float4div - returns arg1 / arg2 */Datumfloat4pl(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT4(0); float8 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 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);}Datumfloat4mi(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);}Datumfloat4mul(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);}Datumfloat4div(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"))); /* Do division in float8, then check for overflow */ result = arg1 / arg2; CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT4(result);}/* * float8pl - returns arg1 + arg2 * float8mi - returns arg1 - arg2 * float8mul - returns arg1 * arg2 * float8div - returns arg1 / arg2 */Datumfloat8pl(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);}Datumfloat8mi(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);}Datumfloat8mul(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);}Datumfloat8div(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);}/* * ==================== * COMPARISON OPERATORS * ==================== *//* * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations */static intfloat4_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; }}Datumfloat4eq(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);}Datumfloat4ne(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);}Datumfloat4lt(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);}Datumfloat4le(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);}Datumfloat4gt(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);}Datumfloat4ge(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);}Datumbtfloat4cmp(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float4 arg2 = PG_GETARG_FLOAT4(1); PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));}/* * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations */static intfloat8_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; }}Datumfloat8eq(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);}Datumfloat8ne(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);}Datumfloat8lt(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);}Datumfloat8le(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);}Datumfloat8gt(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);}Datumfloat8ge(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);}Datumbtfloat8cmp(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));}Datumbtfloat48cmp(PG_FUNCTION_ARGS){ float4 arg1 = PG_GETARG_FLOAT4(0); float8 arg2 = PG_GETARG_FLOAT8(1); /* widen float4 to float8 and then compare */ PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));}Datumbtfloat84cmp(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float4 arg2 = PG_GETARG_FLOAT4(1); /* widen float4 to float8 and then compare */ PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));}/* * =================== * CONVERSION ROUTINES * =================== *//* * ftod - converts a float4 number to a float8 number */Datumftod(PG_FUNCTION_ARGS){ float4 num = PG_GETARG_FLOAT4(0); PG_RETURN_FLOAT8((float8) num);}/* * dtof - converts a float8 number to a float4 number */Datumdtof(PG_FUNCTION_ARGS){ float8 num = PG_GETARG_FLOAT8(0); CHECKFLOATVAL((float4) num, isinf(num), num == 0); PG_RETURN_FLOAT4((float4) num);}/* * dtoi4 - converts a float8 number to an int4 number */Datumdtoi4(PG_FUNCTION_ARGS){ float8 num = PG_GETARG_FLOAT8(0); int32 result; /* 'Inf' is handled by INT_MAX */ if (num < INT_MIN || num > INT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); result = (int32) rint(num); PG_RETURN_INT32(result);}/* * dtoi2 - converts a float8 number to an int2 number */Datumdtoi2(PG_FUNCTION_ARGS){ float8 num = PG_GETARG_FLOAT8(0); if (num < SHRT_MIN || num > SHRT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); PG_RETURN_INT16((int16) rint(num));}/* * i4tod - converts an int4 number to a float8 number */Datumi4tod(PG_FUNCTION_ARGS){ int32 num = PG_GETARG_INT32(0); PG_RETURN_FLOAT8((float8) num);}/* * i2tod - converts an int2 number to a float8 number */Datumi2tod(PG_FUNCTION_ARGS){ int16 num = PG_GETARG_INT16(0); PG_RETURN_FLOAT8((float8) num);}/* * ftoi4 - converts a float4 number to an int4 number */Datumftoi4(PG_FUNCTION_ARGS){ float4 num = PG_GETARG_FLOAT4(0); if (num < INT_MIN || num > INT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); PG_RETURN_INT32((int32) rint(num));}/* * ftoi2 - converts a float4 number to an int2 number */Datumftoi2(PG_FUNCTION_ARGS){ float4 num = PG_GETARG_FLOAT4(0); if (num < SHRT_MIN || num > SHRT_MAX || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); PG_RETURN_INT16((int16) rint(num));}/* * i4tof - converts an int4 number to a float4 number */Datumi4tof(PG_FUNCTION_ARGS){ int32 num = PG_GETARG_INT32(0); PG_RETURN_FLOAT4((float4) num);}/* * i2tof - converts an int2 number to a float4 number */Datumi2tof(PG_FUNCTION_ARGS){ int16 num = PG_GETARG_INT16(0); PG_RETURN_FLOAT4((float4) num);}/* * ======================= * RANDOM FLOAT8 OPERATORS * ======================= *//* * dround - returns ROUND(arg1) */Datumdround(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); PG_RETURN_FLOAT8(rint(arg1));}/* * dceil - returns the smallest integer greater than or * equal to the specified float */Datumdceil(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); PG_RETURN_FLOAT8(ceil(arg1));}/* * dfloor - returns the largest integer lesser than or * equal to the specified float */Datumdfloor(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); PG_RETURN_FLOAT8(floor(arg1));}/* * dsign - returns -1 if the argument is less than 0, 0 * if the argument is equal to 0, and 1 if the * argument is greater than zero. */Datumdsign(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; if (arg1 > 0) result = 1.0; else if (arg1 < 0) result = -1.0; else result = 0.0; PG_RETURN_FLOAT8(result);}/* * dtrunc - returns truncation-towards-zero of arg1, * arg1 >= 0 ... the greatest integer less * than or equal to arg1 * arg1 < 0 ... the least integer greater * than or equal to arg1 */Datumdtrunc(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; if (arg1 >= 0) result = floor(arg1); else result = -floor(-arg1); PG_RETURN_FLOAT8(result);}/* * dsqrt - returns square root of arg1 */Datumdsqrt(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; if (arg1 < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), errmsg("cannot take square root of a negative number"))); result = sqrt(arg1); CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result);}/* * dcbrt - returns cube root of arg1 */Datumdcbrt(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; result = cbrt(arg1); CHECKFLOATVAL(result, isinf(arg1), arg1 == 0); PG_RETURN_FLOAT8(result);}/* * dpow - returns pow(arg1,arg2) */Datumdpow(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg2 = PG_GETARG_FLOAT8(1); float8 result; /* * The SQL spec requires that we emit a particular SQLSTATE error code for * certain error conditions. */ if ((arg1 == 0 && arg2 < 0) || (arg1 < 0 && floor(arg2) != arg2)) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), errmsg("invalid argument for power function"))); /* * pow() sets errno only on some platforms, depending on whether it * follows _IEEE_, _POSIX_, _XOPEN_, or _SVID_, so we try to avoid using * errno. However, some platform/CPU combinations return errno == EDOM * and result == Nan for negative arg1 and very large arg2 (they must be * using something different from our floor() test to decide it's * invalid). Other platforms (HPPA) return errno == ERANGE and a large * (HUGE_VAL) but finite result to signal overflow. */ errno = 0; result = pow(arg1, arg2); if (errno == EDOM && isnan(result)) { if ((fabs(arg1) > 1 && arg2 >= 0) || (fabs(arg1) < 1 && arg2 < 0)) /* The sign of Inf is not significant in this case. */ result = get_float8_infinity(); else if (fabs(arg1) != 1) result = 0; else result = 1; } else if (errno == ERANGE && result != 0 && !isinf(result)) result = get_float8_infinity(); CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); PG_RETURN_FLOAT8(result);}/* * dexp - returns the exponential function of arg1 */Datumdexp(PG_FUNCTION_ARGS){ float8 arg1 = PG_GETARG_FLOAT8(0); float8 result;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -