@ -86,6 +86,38 @@ static double cbrt(double x);
# endif /* HAVE_CBRT */
# endif /* HAVE_CBRT */
/*
* We use these out - of - line ereport ( ) calls to report float overflow ,
* underflow , and zero - divide , because following our usual practice of
* repeating them at each call site would lead to a lot of code bloat .
*
* This does mean that you don ' t get a useful error location indicator .
*/
pg_noinline void
float_overflow_error ( void )
{
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value out of range: overflow " ) ) ) ;
}
pg_noinline void
float_underflow_error ( void )
{
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value out of range: underflow " ) ) ) ;
}
pg_noinline void
float_zero_divide_error ( void )
{
ereport ( ERROR ,
( errcode ( ERRCODE_DIVISION_BY_ZERO ) ,
errmsg ( " division by zero " ) ) ) ;
}
/*
/*
* Returns - 1 if ' val ' represents negative infinity , 1 if ' val '
* Returns - 1 if ' val ' represents negative infinity , 1 if ' val '
* represents ( positive ) infinity , and 0 otherwise . On some platforms ,
* represents ( positive ) infinity , and 0 otherwise . On some platforms ,
@ -1190,10 +1222,15 @@ Datum
dtof ( PG_FUNCTION_ARGS )
dtof ( PG_FUNCTION_ARGS )
{
{
float8 num = PG_GETARG_FLOAT8 ( 0 ) ;
float8 num = PG_GETARG_FLOAT8 ( 0 ) ;
float4 result ;
check_float4_val ( ( float4 ) num , isinf ( num ) , num = = 0 ) ;
result = ( float4 ) num ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( num ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0f ) & & num ! = 0.0 )
float_underflow_error ( ) ;
PG_RETURN_FLOAT4 ( ( float4 ) num ) ;
PG_RETURN_FLOAT4 ( result ) ;
}
}
@ -1444,8 +1481,11 @@ dsqrt(PG_FUNCTION_ARGS)
errmsg ( " cannot take square root of a negative number " ) ) ) ;
errmsg ( " cannot take square root of a negative number " ) ) ) ;
result = sqrt ( arg1 ) ;
result = sqrt ( arg1 ) ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( arg1 ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0 ) & & arg1 ! = 0.0 )
float_underflow_error ( ) ;
check_float8_val ( result , isinf ( arg1 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1460,7 +1500,11 @@ dcbrt(PG_FUNCTION_ARGS)
float8 result ;
float8 result ;
result = cbrt ( arg1 ) ;
result = cbrt ( arg1 ) ;
check_float8_val ( result , isinf ( arg1 ) , arg1 = = 0 ) ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( arg1 ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0 ) & & arg1 ! = 0.0 )
float_underflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1532,7 +1576,11 @@ dpow(PG_FUNCTION_ARGS)
else if ( errno = = ERANGE & & result ! = 0 & & ! isinf ( result ) )
else if ( errno = = ERANGE & & result ! = 0 & & ! isinf ( result ) )
result = get_float8_infinity ( ) ;
result = get_float8_infinity ( ) ;
check_float8_val ( result , isinf ( arg1 ) | | isinf ( arg2 ) , arg1 = = 0 ) ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( arg1 ) & & ! isinf ( arg2 ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0 ) & & arg1 ! = 0.0 )
float_underflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1551,7 +1599,11 @@ dexp(PG_FUNCTION_ARGS)
if ( errno = = ERANGE & & result ! = 0 & & ! isinf ( result ) )
if ( errno = = ERANGE & & result ! = 0 & & ! isinf ( result ) )
result = get_float8_infinity ( ) ;
result = get_float8_infinity ( ) ;
check_float8_val ( result , isinf ( arg1 ) , false ) ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( arg1 ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0 ) )
float_underflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1579,8 +1631,11 @@ dlog1(PG_FUNCTION_ARGS)
errmsg ( " cannot take logarithm of a negative number " ) ) ) ;
errmsg ( " cannot take logarithm of a negative number " ) ) ) ;
result = log ( arg1 ) ;
result = log ( arg1 ) ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( arg1 ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0 ) & & arg1 ! = 1.0 )
float_underflow_error ( ) ;
check_float8_val ( result , isinf ( arg1 ) , arg1 = = 1 ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1609,8 +1664,11 @@ dlog10(PG_FUNCTION_ARGS)
errmsg ( " cannot take logarithm of a negative number " ) ) ) ;
errmsg ( " cannot take logarithm of a negative number " ) ) ) ;
result = log10 ( arg1 ) ;
result = log10 ( arg1 ) ;
if ( unlikely ( isinf ( result ) ) & & ! isinf ( arg1 ) )
float_overflow_error ( ) ;
if ( unlikely ( result = = 0.0 ) & & arg1 ! = 1.0 )
float_underflow_error ( ) ;
check_float8_val ( result , isinf ( arg1 ) , arg1 = = 1 ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1639,8 +1697,9 @@ dacos(PG_FUNCTION_ARGS)
errmsg ( " input is out of range " ) ) ) ;
errmsg ( " input is out of range " ) ) ) ;
result = acos ( arg1 ) ;
result = acos ( arg1 ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
check_float8_val ( result , false , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1669,8 +1728,9 @@ dasin(PG_FUNCTION_ARGS)
errmsg ( " input is out of range " ) ) ) ;
errmsg ( " input is out of range " ) ) ) ;
result = asin ( arg1 ) ;
result = asin ( arg1 ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
check_float8_val ( result , false , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1694,8 +1754,9 @@ datan(PG_FUNCTION_ARGS)
* finite , even if the input is infinite .
* finite , even if the input is infinite .
*/
*/
result = atan ( arg1 ) ;
result = atan ( arg1 ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
check_float8_val ( result , false , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1719,8 +1780,9 @@ datan2(PG_FUNCTION_ARGS)
* should always be finite , even if the inputs are infinite .
* should always be finite , even if the inputs are infinite .
*/
*/
result = atan2 ( arg1 , arg2 ) ;
result = atan2 ( arg1 , arg2 ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
check_float8_val ( result , false , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1759,8 +1821,9 @@ dcos(PG_FUNCTION_ARGS)
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
errmsg ( " input is out of range " ) ) ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
check_float8_val ( result , false , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1787,7 +1850,8 @@ dcot(PG_FUNCTION_ARGS)
errmsg ( " input is out of range " ) ) ) ;
errmsg ( " input is out of range " ) ) ) ;
result = 1.0 / result ;
result = 1.0 / result ;
check_float8_val ( result , true /* cot(0) == Inf */ , true ) ;
/* Not checking for overflow because cot(0) == Inf */
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1812,8 +1876,9 @@ dsin(PG_FUNCTION_ARGS)
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
errmsg ( " input is out of range " ) ) ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
check_float8_val ( result , false , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1838,8 +1903,8 @@ dtan(PG_FUNCTION_ARGS)
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
errmsg ( " input is out of range " ) ) ) ;
/* Not checking for overflow because tan(pi/2) == Inf */
check_float8_val ( result , true /* tan(pi/2) == Inf */ , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -1991,7 +2056,9 @@ dacosd(PG_FUNCTION_ARGS)
else
else
result = 90.0 + asind_q1 ( - arg1 ) ;
result = 90.0 + asind_q1 ( - arg1 ) ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2026,7 +2093,9 @@ dasind(PG_FUNCTION_ARGS)
else
else
result = - asind_q1 ( - arg1 ) ;
result = - asind_q1 ( - arg1 ) ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2056,7 +2125,9 @@ datand(PG_FUNCTION_ARGS)
atan_arg1 = atan ( arg1 ) ;
atan_arg1 = atan ( arg1 ) ;
result = ( atan_arg1 / atan_1_0 ) * 45.0 ;
result = ( atan_arg1 / atan_1_0 ) * 45.0 ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2090,7 +2161,9 @@ datan2d(PG_FUNCTION_ARGS)
atan2_arg1_arg2 = atan2 ( arg1 , arg2 ) ;
atan2_arg1_arg2 = atan2 ( arg1 , arg2 ) ;
result = ( atan2_arg1_arg2 / atan_1_0 ) * 45.0 ;
result = ( atan2_arg1_arg2 / atan_1_0 ) * 45.0 ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2211,7 +2284,9 @@ dcosd(PG_FUNCTION_ARGS)
result = sign * cosd_q1 ( arg1 ) ;
result = sign * cosd_q1 ( arg1 ) ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2276,7 +2351,8 @@ dcotd(PG_FUNCTION_ARGS)
if ( result = = 0.0 )
if ( result = = 0.0 )
result = 0.0 ;
result = 0.0 ;
check_float8_val ( result , true /* cotd(0) == Inf */ , true ) ;
/* Not checking for overflow because cotd(0) == Inf */
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2330,7 +2406,9 @@ dsind(PG_FUNCTION_ARGS)
result = sign * sind_q1 ( arg1 ) ;
result = sign * sind_q1 ( arg1 ) ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2395,7 +2473,8 @@ dtand(PG_FUNCTION_ARGS)
if ( result = = 0.0 )
if ( result = = 0.0 )
result = 0.0 ;
result = 0.0 ;
check_float8_val ( result , true /* tand(90) == Inf */ , true ) ;
/* Not checking for overflow because tand(90) == Inf */
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2462,7 +2541,6 @@ dsinh(PG_FUNCTION_ARGS)
result = get_float8_infinity ( ) ;
result = get_float8_infinity ( ) ;
}
}
check_float8_val ( result , true , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2486,7 +2564,9 @@ dcosh(PG_FUNCTION_ARGS)
if ( errno = = ERANGE )
if ( errno = = ERANGE )
result = get_float8_infinity ( ) ;
result = get_float8_infinity ( ) ;
check_float8_val ( result , true , false ) ;
if ( unlikely ( result = = 0.0 ) )
float_underflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2504,7 +2584,9 @@ dtanh(PG_FUNCTION_ARGS)
*/
*/
result = tanh ( arg1 ) ;
result = tanh ( arg1 ) ;
check_float8_val ( result , false , true ) ;
if ( unlikely ( isinf ( result ) ) )
float_overflow_error ( ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2522,7 +2604,6 @@ dasinh(PG_FUNCTION_ARGS)
*/
*/
result = asinh ( arg1 ) ;
result = asinh ( arg1 ) ;
check_float8_val ( result , true , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2548,7 +2629,6 @@ dacosh(PG_FUNCTION_ARGS)
result = acosh ( arg1 ) ;
result = acosh ( arg1 ) ;
check_float8_val ( result , true , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2583,7 +2663,6 @@ datanh(PG_FUNCTION_ARGS)
else
else
result = atanh ( arg1 ) ;
result = atanh ( arg1 ) ;
check_float8_val ( result , true , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
@ -2784,7 +2863,8 @@ float8_combine(PG_FUNCTION_ARGS)
Sx = float8_pl ( Sx1 , Sx2 ) ;
Sx = float8_pl ( Sx1 , Sx2 ) ;
tmp = Sx1 / N1 - Sx2 / N2 ;
tmp = Sx1 / N1 - Sx2 / N2 ;
Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp * tmp / N ;
Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp * tmp / N ;
check_float8_val ( Sxx , isinf ( Sxx1 ) | | isinf ( Sxx2 ) , true ) ;
if ( unlikely ( isinf ( Sxx ) ) & & ! isinf ( Sxx1 ) & & ! isinf ( Sxx2 ) )
float_overflow_error ( ) ;
}
}
/*
/*
@ -2853,9 +2933,7 @@ float8_accum(PG_FUNCTION_ARGS)
if ( isinf ( Sx ) | | isinf ( Sxx ) )
if ( isinf ( Sx ) | | isinf ( Sxx ) )
{
{
if ( ! isinf ( transvalues [ 1 ] ) & & ! isinf ( newval ) )
if ( ! isinf ( transvalues [ 1 ] ) & & ! isinf ( newval ) )
ereport ( ERROR ,
float_overflow_error ( ) ;
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value out of range: overflow " ) ) ) ;
Sxx = get_float8_nan ( ) ;
Sxx = get_float8_nan ( ) ;
}
}
@ -2929,9 +3007,7 @@ float4_accum(PG_FUNCTION_ARGS)
if ( isinf ( Sx ) | | isinf ( Sxx ) )
if ( isinf ( Sx ) | | isinf ( Sxx ) )
{
{
if ( ! isinf ( transvalues [ 1 ] ) & & ! isinf ( newval ) )
if ( ! isinf ( transvalues [ 1 ] ) & & ! isinf ( newval ) )
ereport ( ERROR ,
float_overflow_error ( ) ;
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value out of range: overflow " ) ) ) ;
Sxx = get_float8_nan ( ) ;
Sxx = get_float8_nan ( ) ;
}
}
@ -3152,9 +3228,7 @@ float8_regr_accum(PG_FUNCTION_ARGS)
( isinf ( Sxy ) & &
( isinf ( Sxy ) & &
! isinf ( transvalues [ 1 ] ) & & ! isinf ( newvalX ) & &
! isinf ( transvalues [ 1 ] ) & & ! isinf ( newvalX ) & &
! isinf ( transvalues [ 3 ] ) & & ! isinf ( newvalY ) ) )
! isinf ( transvalues [ 3 ] ) & & ! isinf ( newvalY ) ) )
ereport ( ERROR ,
float_overflow_error ( ) ;
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value out of range: overflow " ) ) ) ;
if ( isinf ( Sxx ) )
if ( isinf ( Sxx ) )
Sxx = get_float8_nan ( ) ;
Sxx = get_float8_nan ( ) ;
@ -3294,13 +3368,16 @@ float8_regr_combine(PG_FUNCTION_ARGS)
Sx = float8_pl ( Sx1 , Sx2 ) ;
Sx = float8_pl ( Sx1 , Sx2 ) ;
tmp1 = Sx1 / N1 - Sx2 / N2 ;
tmp1 = Sx1 / N1 - Sx2 / N2 ;
Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp1 * tmp1 / N ;
Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp1 * tmp1 / N ;
check_float8_val ( Sxx , isinf ( Sxx1 ) | | isinf ( Sxx2 ) , true ) ;
if ( unlikely ( isinf ( Sxx ) ) & & ! isinf ( Sxx1 ) & & ! isinf ( Sxx2 ) )
float_overflow_error ( ) ;
Sy = float8_pl ( Sy1 , Sy2 ) ;
Sy = float8_pl ( Sy1 , Sy2 ) ;
tmp2 = Sy1 / N1 - Sy2 / N2 ;
tmp2 = Sy1 / N1 - Sy2 / N2 ;
Syy = Syy1 + Syy2 + N1 * N2 * tmp2 * tmp2 / N ;
Syy = Syy1 + Syy2 + N1 * N2 * tmp2 * tmp2 / N ;
check_float8_val ( Syy , isinf ( Syy1 ) | | isinf ( Syy2 ) , true ) ;
if ( unlikely ( isinf ( Syy ) ) & & ! isinf ( Syy1 ) & & ! isinf ( Syy2 ) )
float_overflow_error ( ) ;
Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N ;
Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N ;
check_float8_val ( Sxy , isinf ( Sxy1 ) | | isinf ( Sxy2 ) , true ) ;
if ( unlikely ( isinf ( Sxy ) ) & & ! isinf ( Sxy1 ) & & ! isinf ( Sxy2 ) )
float_overflow_error ( ) ;
}
}
/*
/*