@ -8,52 +8,13 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / utils / adt / float . c , v 1.131 2006 / 12 / 23 02 : 13 : 24 momjian Exp $
* $ PostgreSQL : pgsql / src / backend / utils / adt / float . c , v 1.132 2007 / 01 / 02 20 : 00 : 49 momjian Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/*----------
* OLD COMMENTS
* Basic float4 ops :
* float4in , float4out , float4recv , float4send
* float4abs , float4um , float4up
* Basic float8 ops :
* float8in , float8out , float8recv , float8send
* float8abs , float8um , float8up
* Arithmetic operators :
* float4pl , float4mi , float4mul , float4div
* float8pl , float8mi , float8mul , float8div
* Comparison operators :
* float4eq , float4ne , float4lt , float4le , float4gt , float4ge , float4cmp
* float8eq , float8ne , float8lt , float8le , float8gt , float8ge , float8cmp
* Conversion routines :
* ftod , dtof , i4tod , dtoi4 , i2tod , dtoi2 , itof , ftoi , i2tof , ftoi2
*
* Random float8 ops :
* dround , dtrunc , dsqrt , dcbrt , dpow , dexp , dlog1
* Arithmetic operators :
* float48pl , float48mi , float48mul , float48div
* float84pl , float84mi , float84mul , float84div
* Comparison operators :
* float48eq , float48ne , float48lt , float48le , float48gt , float48ge
* float84eq , float84ne , float84lt , float84le , float84gt , float84ge
*
* ( You can do the arithmetic and comparison stuff using conversion
* routines , but then you pay the overhead of invoking a separate
* conversion function . . . )
*
* XXX GLUESOME STUFF . FIX IT ! - AY ' 94
*
* Added some additional conversion routines and cleaned up
* a bit of the existing code . Need to change the error checking
* for calls to pow ( ) , exp ( ) since on some machines ( my Linux box
* included ) these routines do not set errno . - tgl 97 / 05 / 10
* - - - - - - - - - -
*/
# include "postgres.h"
# include <ctype.h>
# include <float.h>
# include <math.h>
# include <limits.h>
/* for finite() on Solaris */
@ -91,21 +52,30 @@ static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
# define MAXFLOATWIDTH 64
# define MAXDOUBLEWIDTH 128
/* ========== USER I/O ROUTINES ========== */
/*
* 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 )
# define FLOAT4_MAX FLT_MAX
# define FLOAT4_MIN FLT_MIN
# define FLOAT8_MAX DBL_MAX
# define FLOAT8_MIN DBL_MIN
/* ========== USER I/O ROUTINES ========== */
/* Configurable GUC parameter */
int extra_float_digits = 0 ; /* Added to DBL_DIG or FLT_DIG */
static void CheckFloat4Val ( double val ) ;
static void CheckFloat8Val ( double val ) ;
static int float4_cmp_internal ( float4 a , float4 b ) ;
static int float8_cmp_internal ( float8 a , float8 b ) ;
@ -204,44 +174,6 @@ is_infinite(double val)
}
/*
* check to see if a float4 val is outside of the FLOAT4_MIN ,
* FLOAT4_MAX bounds .
*
* raise an ereport ( ) error if it is
*/
static void
CheckFloat4Val ( double val )
{
if ( fabs ( val ) > FLOAT4_MAX )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " type \" real \" value out of range: overflow " ) ) ) ;
if ( val ! = 0.0 & & fabs ( val ) < FLOAT4_MIN )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " type \" real \" value out of range: underflow " ) ) ) ;
}
/*
* check to see if a float8 val is outside of the FLOAT8_MIN ,
* FLOAT8_MAX bounds .
*
* raise an ereport ( ) error if it is
*/
static void
CheckFloat8Val ( double val )
{
if ( fabs ( val ) > FLOAT8_MAX )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " type \" double precision \" value out of range: overflow " ) ) ) ;
if ( val ! = 0.0 & & fabs ( val ) < FLOAT8_MIN )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " type \" double precision \" value out of range: underflow " ) ) ) ;
}
/*
* float4in - converts " num " to float
* restricted syntax :
@ -369,8 +301,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
*/
if ( ! isinf ( val ) )
CheckFloat4Val ( val ) ;
CHECKFLOATVAL ( ( float4 ) val , isinf ( val ) , val = = 0 ) ;
PG_RETURN_FLOAT4 ( ( float4 ) val ) ;
}
@ -558,8 +489,7 @@ float8in(PG_FUNCTION_ARGS)
errmsg ( " invalid input syntax for type double precision: \" %s \" " ,
orig_num ) ) ) ;
if ( ! isinf ( val ) )
CheckFloat8Val ( val ) ;
CHECKFLOATVAL ( val , true , true ) ;
PG_RETURN_FLOAT8 ( val ) ;
}
@ -652,8 +582,12 @@ Datum
float4um ( PG_FUNCTION_ARGS )
{
float4 arg1 = PG_GETARG_FLOAT4 ( 0 ) ;
float4 result ;
result = ( ( arg1 ! = 0 ) ? - ( arg1 ) : arg1 ) ;
PG_RETURN_FLOAT4 ( ( float4 ) - arg1 ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT4 ( result ) ;
}
Datum
@ -705,12 +639,8 @@ Datum
float8abs ( PG_FUNCTION_ARGS )
{
float8 arg1 = PG_GETARG_FLOAT8 ( 0 ) ;
float8 result ;
result = fabs ( arg1 ) ;
CheckFloat8Val ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( fabs ( arg1 ) ) ;
}
@ -725,7 +655,7 @@ float8um(PG_FUNCTION_ARGS)
result = ( ( arg1 ! = 0 ) ? - ( arg1 ) : arg1 ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -781,13 +711,20 @@ float8smaller(PG_FUNCTION_ARGS)
Datum
float4pl ( PG_FUNCTION_ARGS )
{
float4 arg1 = PG_GETARG_FLOAT4 ( 0 ) ;
float4 arg2 = PG_GETARG_FLOAT4 ( 1 ) ;
double result ;
float8 arg1 = PG_GETARG_FLOAT4 ( 0 ) ;
float8 arg2 = PG_GETARG_FLOAT4 ( 1 ) ;
float4 result ;
result = arg1 + arg2 ;
CheckFloat4Val ( result ) ;
PG_RETURN_FLOAT4 ( ( float4 ) result ) ;
/*
* 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 ) ;
}
Datum
@ -795,11 +732,11 @@ float4mi(PG_FUNCTION_ARGS)
{
float4 arg1 = PG_GETARG_FLOAT4 ( 0 ) ;
float4 arg2 = PG_GETARG_FLOAT4 ( 1 ) ;
double result ;
float4 result ;
result = arg1 - arg2 ;
CheckFloat4Val ( result ) ;
PG_RETURN_FLOAT4 ( ( float4 ) result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT4 ( result ) ;
}
Datum
@ -807,11 +744,12 @@ float4mul(PG_FUNCTION_ARGS)
{
float4 arg1 = PG_GETARG_FLOAT4 ( 0 ) ;
float4 arg2 = PG_GETARG_FLOAT4 ( 1 ) ;
double result ;
float4 result ;
result = arg1 * arg2 ;
CheckFloat4Val ( result ) ;
PG_RETURN_FLOAT4 ( ( float4 ) result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) ,
arg1 = = 0 | | arg2 = = 0 ) ;
PG_RETURN_FLOAT4 ( result ) ;
}
Datum
@ -819,7 +757,7 @@ float4div(PG_FUNCTION_ARGS)
{
float4 arg1 = PG_GETARG_FLOAT4 ( 0 ) ;
float4 arg2 = PG_GETARG_FLOAT4 ( 1 ) ;
double result ;
float4 result ;
if ( arg2 = = 0.0 )
ereport ( ERROR ,
@ -827,10 +765,10 @@ float4div(PG_FUNCTION_ARGS)
errmsg ( " division by zero " ) ) ) ;
/* Do division in float8, then check for overflow */
result = ( float8 ) arg1 / ( float8 ) arg2 ;
result = arg1 / arg2 ;
CheckFloat4Val ( result ) ;
PG_RETURN_FLOAT4 ( ( float4 ) result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT4 ( result ) ;
}
/*
@ -848,7 +786,7 @@ float8pl(PG_FUNCTION_ARGS)
result = arg1 + arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -861,7 +799,7 @@ float8mi(PG_FUNCTION_ARGS)
result = arg1 - arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -874,7 +812,8 @@ float8mul(PG_FUNCTION_ARGS)
result = arg1 * arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) ,
arg1 = = 0 | | arg2 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -892,7 +831,7 @@ float8div(PG_FUNCTION_ARGS)
result = arg1 / arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1142,7 +1081,7 @@ dtof(PG_FUNCTION_ARGS)
{
float8 num = PG_GETARG_FLOAT8 ( 0 ) ;
CheckFloat4Val ( num ) ;
CHECKFLOATVAL ( ( float4 ) num , isinf ( num ) , num = = 0 ) ;
PG_RETURN_FLOAT4 ( ( float4 ) num ) ;
}
@ -1157,7 +1096,8 @@ dtoi4(PG_FUNCTION_ARGS)
float8 num = PG_GETARG_FLOAT8 ( 0 ) ;
int32 result ;
if ( num < INT_MIN | | num > INT_MAX )
/* '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 " ) ) ) ;
@ -1174,15 +1114,13 @@ Datum
dtoi2 ( PG_FUNCTION_ARGS )
{
float8 num = PG_GETARG_FLOAT8 ( 0 ) ;
int16 result ;
if ( num < SHRT_MIN | | num > SHRT_MAX )
if ( num < SHRT_MIN | | num > SHRT_MAX | | isnan ( num ) )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " smallint out of range " ) ) ) ;
result = ( int16 ) rint ( num ) ;
PG_RETURN_INT16 ( result ) ;
PG_RETURN_INT16 ( ( int16 ) rint ( num ) ) ;
}
@ -1193,10 +1131,8 @@ Datum
i4tod ( PG_FUNCTION_ARGS )
{
int32 num = PG_GETARG_INT32 ( 0 ) ;
float8 result ;
result = num ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( ( float8 ) num ) ;
}
@ -1207,10 +1143,8 @@ Datum
i2tod ( PG_FUNCTION_ARGS )
{
int16 num = PG_GETARG_INT16 ( 0 ) ;
float8 result ;
result = num ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( ( float8 ) num ) ;
}
@ -1221,15 +1155,13 @@ Datum
ftoi4 ( PG_FUNCTION_ARGS )
{
float4 num = PG_GETARG_FLOAT4 ( 0 ) ;
int32 result ;
if ( num < INT_MIN | | num > 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 ) ;
PG_RETURN_INT32 ( ( int32 ) rint ( num ) ) ;
}
@ -1240,29 +1172,25 @@ Datum
ftoi2 ( PG_FUNCTION_ARGS )
{
float4 num = PG_GETARG_FLOAT4 ( 0 ) ;
int16 result ;
if ( num < SHRT_MIN | | num > SHRT_MAX )
if ( num < SHRT_MIN | | num > SHRT_MAX | | isnan ( num ) )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " smallint out of range " ) ) ) ;
result = ( int16 ) rint ( num ) ;
PG_RETURN_INT16 ( result ) ;
PG_RETURN_INT16 ( ( int16 ) rint ( num ) ) ;
}
/*
* i4tof - converts an int4 number to a float8 number
* i4tof - converts an int4 number to a float4 number
*/
Datum
i4tof ( PG_FUNCTION_ARGS )
{
int32 num = PG_GETARG_INT32 ( 0 ) ;
float4 result ;
result = num ;
PG_RETURN_FLOAT4 ( result ) ;
PG_RETURN_FLOAT4 ( ( float4 ) num ) ;
}
@ -1273,10 +1201,8 @@ Datum
i2tof ( PG_FUNCTION_ARGS )
{
int16 num = PG_GETARG_INT16 ( 0 ) ;
float4 result ;
result = num ;
PG_RETURN_FLOAT4 ( result ) ;
PG_RETURN_FLOAT4 ( ( float4 ) num ) ;
}
@ -1395,11 +1321,8 @@ Datum
dround ( PG_FUNCTION_ARGS )
{
float8 arg1 = PG_GETARG_FLOAT8 ( 0 ) ;
float8 result ;
result = rint ( arg1 ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( rint ( arg1 ) ) ;
}
/*
@ -1485,7 +1408,7 @@ dsqrt(PG_FUNCTION_ARGS)
result = sqrt ( arg1 ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1500,6 +1423,7 @@ dcbrt(PG_FUNCTION_ARGS)
float8 result ;
result = cbrt ( arg1 ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1530,16 +1454,12 @@ dpow(PG_FUNCTION_ARGS)
*/
errno = 0 ;
result = pow ( arg1 , arg2 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " result is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1555,21 +1475,16 @@ dexp(PG_FUNCTION_ARGS)
/*
* We must check both for errno getting set and for a NaN result , in order
* to deal with the vagaries of different platforms . Also , a zero result
* implies unreported underflow .
* to deal with the vagaries of different platforms .
*/
errno = 0 ;
result = exp ( arg1 ) ;
if ( errno ! = 0 | | result = = 0.0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " result is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , false ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1598,7 +1513,7 @@ dlog1(PG_FUNCTION_ARGS)
result = log ( arg1 ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , arg1 = = 1 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1628,7 +1543,7 @@ dlog10(PG_FUNCTION_ARGS)
result = log10 ( arg1 ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , arg1 = = 1 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1644,16 +1559,12 @@ dacos(PG_FUNCTION_ARGS)
errno = 0 ;
result = acos ( arg1 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1669,16 +1580,12 @@ dasin(PG_FUNCTION_ARGS)
errno = 0 ;
result = asin ( arg1 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1694,16 +1601,12 @@ datan(PG_FUNCTION_ARGS)
errno = 0 ;
result = atan ( arg1 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1720,16 +1623,12 @@ datan2(PG_FUNCTION_ARGS)
errno = 0 ;
result = atan2 ( arg1 , arg2 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1745,16 +1644,12 @@ dcos(PG_FUNCTION_ARGS)
errno = 0 ;
result = cos ( arg1 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1770,17 +1665,13 @@ dcot(PG_FUNCTION_ARGS)
errno = 0 ;
result = tan ( arg1 ) ;
if ( errno ! = 0 | | result = = 0.0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
result = 1.0 / result ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , true /* cotan(pi/2) == inf */ , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1796,16 +1687,12 @@ dsin(PG_FUNCTION_ARGS)
errno = 0 ;
result = sin ( arg1 ) ;
if ( errno ! = 0
# ifdef HAVE_FINITE
| | ! finite ( result )
# endif
)
if ( errno ! = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1830,7 +1717,7 @@ dtan(PG_FUNCTION_ARGS)
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " input is out of range " ) ) ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , true /* tan(pi/2) == Inf */ , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1846,7 +1733,7 @@ degrees(PG_FUNCTION_ARGS)
result = arg1 * ( 180.0 / M_PI ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1872,7 +1759,7 @@ radians(PG_FUNCTION_ARGS)
result = arg1 * ( M_PI / 180.0 ) ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -1963,8 +1850,10 @@ float8_accum(PG_FUNCTION_ARGS)
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
@ -1999,25 +1888,24 @@ Datum
float4_accum ( PG_FUNCTION_ARGS )
{
ArrayType * transarray = PG_GETARG_ARRAYTYPE_P ( 0 ) ;
float4 newval4 = PG_GETARG_FLOAT4 ( 1 ) ;
/* do computations as float8 */
float8 newval = PG_GETARG_FLOAT4 ( 1 ) ;
float8 * transvalues ;
float8 N ,
sumX ,
sumX2 ,
newval ;
sumX2 ;
transvalues = check_float8_array ( transarray , " float4_accum " , 3 ) ;
N = transvalues [ 0 ] ;
sumX = transvalues [ 1 ] ;
sumX2 = transvalues [ 2 ] ;
/* Do arithmetic in float8 for best accuracy */
newval = newval4 ;
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
@ -2088,6 +1976,7 @@ float8_var_pop(PG_FUNCTION_ARGS)
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 )
@ -2116,6 +2005,7 @@ float8_var_samp(PG_FUNCTION_ARGS)
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 )
@ -2144,6 +2034,7 @@ float8_stddev_pop(PG_FUNCTION_ARGS)
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 )
@ -2172,6 +2063,7 @@ float8_stddev_samp(PG_FUNCTION_ARGS)
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 )
@ -2220,11 +2112,17 @@ float8_regr_accum(PG_FUNCTION_ARGS)
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
@ -2282,6 +2180,7 @@ float8_regr_sxx(PG_FUNCTION_ARGS)
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 )
@ -2310,6 +2209,7 @@ float8_regr_syy(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numerator = N * sumY2 - sumY * sumY ;
CHECKFLOATVAL ( numerator , isinf ( sumY2 ) | | isinf ( sumY ) , true ) ;
/* Watch out for roundoff error producing a negative numerator */
if ( numerator < = 0.0 )
@ -2340,6 +2240,8 @@ float8_regr_sxy(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numerator = N * sumXY - sumX * sumY ;
CHECKFLOATVAL ( numerator , isinf ( sumXY ) | | isinf ( sumX ) | |
isinf ( sumY ) , true ) ;
/* A negative result is valid here */
@ -2406,6 +2308,8 @@ float8_covar_pop(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numerator = N * sumXY - sumX * sumY ;
CHECKFLOATVAL ( numerator , isinf ( sumXY ) | | isinf ( sumX ) | |
isinf ( sumY ) , true ) ;
PG_RETURN_FLOAT8 ( numerator / ( N * N ) ) ;
}
@ -2432,6 +2336,8 @@ float8_covar_samp(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numerator = N * sumXY - sumX * sumY ;
CHECKFLOATVAL ( numerator , isinf ( sumXY ) | | isinf ( sumX ) | |
isinf ( sumY ) , true ) ;
PG_RETURN_FLOAT8 ( numerator / ( N * ( N - 1.0 ) ) ) ;
}
@ -2464,8 +2370,12 @@ float8_corr(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numeratorX = N * sumX2 - sumX * sumX ;
CHECKFLOATVAL ( numeratorX , isinf ( sumX2 ) | | isinf ( sumX ) , true ) ;
numeratorY = N * sumY2 - sumY * sumY ;
CHECKFLOATVAL ( numeratorY , isinf ( sumY2 ) | | isinf ( sumY ) , true ) ;
numeratorXY = N * sumXY - sumX * sumY ;
CHECKFLOATVAL ( numeratorXY , isinf ( sumXY ) | | isinf ( sumX ) | |
isinf ( sumY ) , true ) ;
if ( numeratorX < = 0 | | numeratorY < = 0 )
PG_RETURN_NULL ( ) ;
@ -2501,8 +2411,12 @@ float8_regr_r2(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numeratorX = N * sumX2 - sumX * sumX ;
CHECKFLOATVAL ( numeratorX , isinf ( sumX2 ) | | isinf ( sumX ) , true ) ;
numeratorY = N * sumY2 - sumY * sumY ;
CHECKFLOATVAL ( numeratorY , isinf ( sumY2 ) | | isinf ( sumY ) , true ) ;
numeratorXY = N * sumXY - sumX * sumY ;
CHECKFLOATVAL ( numeratorXY , isinf ( sumXY ) | | isinf ( sumX ) | |
isinf ( sumY ) , true ) ;
if ( numeratorX < = 0 )
PG_RETURN_NULL ( ) ;
/* per spec, horizontal line produces 1.0 */
@ -2538,7 +2452,10 @@ float8_regr_slope(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numeratorX = N * sumX2 - sumX * sumX ;
CHECKFLOATVAL ( numeratorX , isinf ( sumX2 ) | | isinf ( sumX ) , true ) ;
numeratorXY = N * sumXY - sumX * sumY ;
CHECKFLOATVAL ( numeratorXY , isinf ( sumXY ) | | isinf ( sumX ) | |
isinf ( sumY ) , true ) ;
if ( numeratorX < = 0 )
PG_RETURN_NULL ( ) ;
@ -2570,7 +2487,10 @@ float8_regr_intercept(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
numeratorX = N * sumX2 - sumX * sumX ;
CHECKFLOATVAL ( numeratorX , isinf ( sumX2 ) | | isinf ( sumX ) , true ) ;
numeratorXXY = sumY * sumX2 - sumX * sumXY ;
CHECKFLOATVAL ( numeratorXXY , isinf ( sumY ) | | isinf ( sumX2 ) | |
isinf ( sumX ) | | isinf ( sumXY ) , true ) ;
if ( numeratorX < = 0 )
PG_RETURN_NULL ( ) ;
@ -2598,7 +2518,7 @@ float48pl(PG_FUNCTION_ARGS)
float8 result ;
result = arg1 + arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2610,7 +2530,7 @@ float48mi(PG_FUNCTION_ARGS)
float8 result ;
result = arg1 - arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2622,7 +2542,8 @@ float48mul(PG_FUNCTION_ARGS)
float8 result ;
result = arg1 * arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) ,
arg1 = = 0 | | arg2 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2639,7 +2560,7 @@ float48div(PG_FUNCTION_ARGS)
errmsg ( " division by zero " ) ) ) ;
result = arg1 / arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2658,7 +2579,7 @@ float84pl(PG_FUNCTION_ARGS)
result = arg1 + arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2671,7 +2592,7 @@ float84mi(PG_FUNCTION_ARGS)
result = arg1 - arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , true ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2684,7 +2605,8 @@ float84mul(PG_FUNCTION_ARGS)
result = arg1 * arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) ,
arg1 = = 0 | | arg2 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
@ -2702,7 +2624,7 @@ float84div(PG_FUNCTION_ARGS)
result = arg1 / arg2 ;
CheckFloat8Val ( result ) ;
CHECKFLOATVAL ( result , isinf ( arg1 ) | | isinf ( arg2 ) , arg1 = = 0 ) ;
PG_RETURN_FLOAT8 ( result ) ;
}