summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/float.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r--src/backend/utils/adt/float.c1999
1 files changed, 0 insertions, 1999 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
deleted file mode 100644
index 84233ebd1c4..00000000000
--- a/src/backend/utils/adt/float.c
+++ /dev/null
@@ -1,1999 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * float.c
- * Functions for the built-in floating-point types.
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.79 2002/06/20 20:29:37 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-/*----------
- * OLD COMMENTS
- * Basic float4 ops:
- * float4in, float4out, float4abs, float4um, float4up
- * Basic float8 ops:
- * float8in, float8out, 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 <errno.h>
-#include <float.h> /* faked on sunos4 */
-#include <math.h>
-
-#include <limits.h>
-/* for finite() on Solaris */
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#include "fmgr.h"
-#include "utils/array.h"
-#include "utils/builtins.h"
-
-
-#if !(NeXT && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_2)
- /* NS3.3 has conflicting declarations of these in <math.h> */
-
-#ifndef atof
-extern double atof(const char *p);
-#endif
-
-#ifndef HAVE_CBRT
-#define cbrt my_cbrt
-static double cbrt(double x);
-
-#else
-#if !defined(nextstep)
-extern double cbrt(double x);
-#endif
-#endif /* HAVE_CBRT */
-
-#ifndef HAVE_RINT
-#define rint my_rint
-static double rint(double x);
-
-#else
-extern double rint(double x);
-#endif /* HAVE_RINT */
-#endif /* NeXT check */
-
-
-static void CheckFloat4Val(double val);
-static void CheckFloat8Val(double val);
-
-#ifndef M_PI
-/* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
-#define M_PI 3.14159265358979323846
-#endif
-
-#ifndef NAN
-#define NAN (0.0/0.0)
-#endif
-
-#ifndef SHRT_MAX
-#define SHRT_MAX 32767
-#endif
-#ifndef SHRT_MIN
-#define SHRT_MIN (-32768)
-#endif
-
-#define FORMAT 'g' /* use "g" output format as standard
- * format */
-/* not sure what the following should be, but better to make it over-sufficient */
-#define MAXFLOATWIDTH 64
-#define MAXDOUBLEWIDTH 128
-
-/* ========== USER I/O ROUTINES ========== */
-
-
-#define FLOAT4_MAX FLT_MAX
-#define FLOAT4_MIN FLT_MIN
-#define FLOAT8_MAX DBL_MAX
-#define FLOAT8_MIN DBL_MIN
-
-
-/*
- check to see if a float4 val is outside of
- the FLOAT4_MIN, FLOAT4_MAX bounds.
-
- raise an elog warning if it is
-*/
-static void
-CheckFloat4Val(double val)
-{
- /*
- * defining unsafe floats's will make float4 and float8 ops faster at
- * the cost of safety, of course!
- */
-#ifdef UNSAFE_FLOATS
- return;
-#else
- if (fabs(val) > FLOAT4_MAX)
- elog(ERROR, "Bad float4 input format -- overflow");
- if (val != 0.0 && fabs(val) < FLOAT4_MIN)
- elog(ERROR, "Bad float4 input format -- underflow");
- return;
-#endif /* UNSAFE_FLOATS */
-}
-
-/*
- check to see if a float8 val is outside of
- the FLOAT8_MIN, FLOAT8_MAX bounds.
-
- raise an elog warning if it is
-*/
-static void
-CheckFloat8Val(double val)
-{
- /*
- * defining unsafe floats's will make float4 and float8 ops faster at
- * the cost of safety, of course!
- */
-#ifdef UNSAFE_FLOATS
- return;
-#else
- if (fabs(val) > FLOAT8_MAX)
- elog(ERROR, "Bad float8 input format -- overflow");
- if (val != 0.0 && fabs(val) < FLOAT8_MIN)
- elog(ERROR, "Bad float8 input format -- underflow");
- return;
-#endif /* UNSAFE_FLOATS */
-}
-
-/*
- * float4in - converts "num" to float
- * restricted syntax:
- * {<sp>} [+|-] {digit} [.{digit}] [<exp>]
- * where <sp> is a space, digit is 0-9,
- * <exp> is "e" or "E" followed by an integer.
- */
-Datum
-float4in(PG_FUNCTION_ARGS)
-{
- char *num = PG_GETARG_CSTRING(0);
- double val;
- char *endptr;
-
- errno = 0;
- val = strtod(num, &endptr);
- if (*endptr != '\0')
- {
- /*
- * XXX we should accept "Infinity" and "-Infinity" too, but what
- * are the correct values to assign? HUGE_VAL will provoke an
- * error from CheckFloat4Val.
- */
- if (strcasecmp(num, "NaN") == 0)
- val = NAN;
- else
- elog(ERROR, "Bad float4 input format '%s'", num);
- }
- else
- {
- if (errno == ERANGE)
- elog(ERROR, "Input '%s' is out of range for float4", num);
- }
-
- /*
- * if we get here, we have a legal double, still need to check to see
- * if it's a legal float
- */
- CheckFloat4Val(val);
-
- PG_RETURN_FLOAT4((float4) val);
-}
-
-/*
- * float4out - converts a float4 number to a string
- * using a standard output format
- */
-Datum
-float4out(PG_FUNCTION_ARGS)
-{
- float4 num = PG_GETARG_FLOAT4(0);
- char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
- int infflag;
-
- if (isnan(num))
- PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
- infflag = isinf(num);
- if (infflag > 0)
- PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));
- if (infflag < 0)
- PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));
-
- sprintf(ascii, "%.*g", FLT_DIG, num);
- PG_RETURN_CSTRING(ascii);
-}
-
-/*
- * float8in - converts "num" to float8
- * restricted syntax:
- * {<sp>} [+|-] {digit} [.{digit}] [<exp>]
- * where <sp> is a space, digit is 0-9,
- * <exp> is "e" or "E" followed by an integer.
- */
-Datum
-float8in(PG_FUNCTION_ARGS)
-{
- char *num = PG_GETARG_CSTRING(0);
- double val;
- char *endptr;
-
- errno = 0;
- val = strtod(num, &endptr);
- if (*endptr != '\0')
- {
- if (strcasecmp(num, "NaN") == 0)
- val = NAN;
- else if (strcasecmp(num, "Infinity") == 0)
- val = HUGE_VAL;
- else if (strcasecmp(num, "-Infinity") == 0)
- val = -HUGE_VAL;
- else
- elog(ERROR, "Bad float8 input format '%s'", num);
- }
- else
- {
- if (errno == ERANGE)
- elog(ERROR, "Input '%s' is out of range for float8", num);
- }
-
- CheckFloat8Val(val);
-
- PG_RETURN_FLOAT8(val);
-}
-
-
-/*
- * float8out - converts float8 number to a string
- * using a standard output format
- */
-Datum
-float8out(PG_FUNCTION_ARGS)
-{
- float8 num = PG_GETARG_FLOAT8(0);
- char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
- int infflag;
-
- if (isnan(num))
- PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
- infflag = isinf(num);
- if (infflag > 0)
- PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));
- if (infflag < 0)
- PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));
-
- sprintf(ascii, "%.*g", DBL_DIG, num);
- PG_RETURN_CSTRING(ascii);
-}
-
-/* ========== PUBLIC ROUTINES ========== */
-
-
-/*
- * ======================
- * FLOAT4 BASE OPERATIONS
- * ======================
- */
-
-/*
- * float4abs - returns |arg1| (absolute value)
- */
-Datum
-float4abs(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
-
- PG_RETURN_FLOAT4((float4) fabs(arg1));
-}
-
-/*
- * float4um - returns -arg1 (unary minus)
- */
-Datum
-float4um(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
-
- PG_RETURN_FLOAT4((float4) -arg1);
-}
-
-Datum
-float4up(PG_FUNCTION_ARGS)
-{
- float4 arg = PG_GETARG_FLOAT4(0);
-
- PG_RETURN_FLOAT4(arg);
-}
-
-Datum
-float4larger(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- float4 result;
-
- result = ((arg1 > arg2) ? arg1 : arg2);
- PG_RETURN_FLOAT4(result);
-}
-
-Datum
-float4smaller(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- float4 result;
-
- result = ((arg1 < arg2) ? arg1 : arg2);
- PG_RETURN_FLOAT4(result);
-}
-
-/*
- * ======================
- * FLOAT8 BASE OPERATIONS
- * ======================
- */
-
-/*
- * float8abs - returns |arg1| (absolute value)
- */
-Datum
-float8abs(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- result = fabs(arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * float8um - returns -arg1 (unary minus)
- */
-Datum
-float8um(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- result = ((arg1 != 0) ? -(arg1) : arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float8up(PG_FUNCTION_ARGS)
-{
- float8 arg = PG_GETARG_FLOAT8(0);
-
- PG_RETURN_FLOAT8(arg);
-}
-
-Datum
-float8larger(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = ((arg1 > arg2) ? arg1 : arg2);
-
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float8smaller(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = ((arg1 < arg2) ? arg1 : arg2);
-
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * ====================
- * ARITHMETIC OPERATORS
- * ====================
- */
-
-/*
- * float4pl - returns arg1 + arg2
- * float4mi - returns arg1 - arg2
- * float4mul - returns arg1 * arg2
- * float4div - returns arg1 / arg2
- */
-Datum
-float4pl(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- double result;
-
- result = arg1 + arg2;
- CheckFloat4Val(result);
- PG_RETURN_FLOAT4((float4) result);
-}
-
-Datum
-float4mi(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- double result;
-
- result = arg1 - arg2;
- CheckFloat4Val(result);
- PG_RETURN_FLOAT4((float4) result);
-}
-
-Datum
-float4mul(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- double result;
-
- result = arg1 * arg2;
- CheckFloat4Val(result);
- PG_RETURN_FLOAT4((float4) result);
-}
-
-Datum
-float4div(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- double result;
-
- if (arg2 == 0.0)
- elog(ERROR, "float4div: divide by zero error");
-
- /* Do division in float8, then check for overflow */
- result = (float8) arg1 / (float8) arg2;
-
- CheckFloat4Val(result);
- PG_RETURN_FLOAT4((float4) result);
-}
-
-/*
- * float8pl - returns arg1 + arg2
- * float8mi - returns arg1 - arg2
- * float8mul - returns arg1 * arg2
- * float8div - returns arg1 / arg2
- */
-Datum
-float8pl(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = arg1 + arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float8mi(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = arg1 - arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float8mul(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = arg1 * arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float8div(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- if (arg2 == 0.0)
- elog(ERROR, "float8div: divide by zero error");
-
- result = arg1 / arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * ====================
- * COMPARISON OPERATORS
- * ====================
- */
-
-/*
- * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
- */
-static 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;
- }
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-btfloat4cmp(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 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;
- }
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-btfloat8cmp(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
-
- PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
-}
-
-
-/*
- * ===================
- * CONVERSION ROUTINES
- * ===================
- */
-
-/*
- * ftod - converts a float4 number to a float8 number
- */
-Datum
-ftod(PG_FUNCTION_ARGS)
-{
- float4 num = PG_GETARG_FLOAT4(0);
-
- PG_RETURN_FLOAT8((float8) num);
-}
-
-
-/*
- * dtof - converts a float8 number to a float4 number
- */
-Datum
-dtof(PG_FUNCTION_ARGS)
-{
- float8 num = PG_GETARG_FLOAT8(0);
-
- CheckFloat4Val(num);
-
- PG_RETURN_FLOAT4((float4) num);
-}
-
-
-/*
- * dtoi4 - converts a float8 number to an int4 number
- */
-Datum
-dtoi4(PG_FUNCTION_ARGS)
-{
- float8 num = PG_GETARG_FLOAT8(0);
- int32 result;
-
- if ((num < INT_MIN) || (num > INT_MAX))
- elog(ERROR, "dtoi4: integer out of range");
-
- result = (int32) rint(num);
- PG_RETURN_INT32(result);
-}
-
-
-/*
- * dtoi2 - converts a float8 number to an int2 number
- */
-Datum
-dtoi2(PG_FUNCTION_ARGS)
-{
- float8 num = PG_GETARG_FLOAT8(0);
- int16 result;
-
- if ((num < SHRT_MIN) || (num > SHRT_MAX))
- elog(ERROR, "dtoi2: integer out of range");
-
- result = (int16) rint(num);
- PG_RETURN_INT16(result);
-}
-
-
-/*
- * i4tod - converts an int4 number to a float8 number
- */
-Datum
-i4tod(PG_FUNCTION_ARGS)
-{
- int32 num = PG_GETARG_INT32(0);
- float8 result;
-
- result = num;
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * i2tod - converts an int2 number to a float8 number
- */
-Datum
-i2tod(PG_FUNCTION_ARGS)
-{
- int16 num = PG_GETARG_INT16(0);
- float8 result;
-
- result = num;
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * ftoi4 - converts a float4 number to an int4 number
- */
-Datum
-ftoi4(PG_FUNCTION_ARGS)
-{
- float4 num = PG_GETARG_FLOAT4(0);
- int32 result;
-
- if ((num < INT_MIN) || (num > INT_MAX))
- elog(ERROR, "ftoi4: integer out of range");
-
- result = (int32) rint(num);
- PG_RETURN_INT32(result);
-}
-
-
-/*
- * ftoi2 - converts a float4 number to an int2 number
- */
-Datum
-ftoi2(PG_FUNCTION_ARGS)
-{
- float4 num = PG_GETARG_FLOAT4(0);
- int16 result;
-
- if ((num < SHRT_MIN) || (num > SHRT_MAX))
- elog(ERROR, "ftoi2: integer out of range");
-
- result = (int16) rint(num);
- PG_RETURN_INT16(result);
-}
-
-
-/*
- * i4tof - converts an int4 number to a float8 number
- */
-Datum
-i4tof(PG_FUNCTION_ARGS)
-{
- int32 num = PG_GETARG_INT32(0);
- float4 result;
-
- result = num;
- PG_RETURN_FLOAT4(result);
-}
-
-
-/*
- * i2tof - converts an int2 number to a float4 number
- */
-Datum
-i2tof(PG_FUNCTION_ARGS)
-{
- int16 num = PG_GETARG_INT16(0);
- float4 result;
-
- result = num;
- PG_RETURN_FLOAT4(result);
-}
-
-
-/*
- * float8_text - converts a float8 number to a text string
- */
-Datum
-float8_text(PG_FUNCTION_ARGS)
-{
- float8 num = PG_GETARG_FLOAT8(0);
- text *result;
- int len;
- char *str;
-
- str = DatumGetCString(DirectFunctionCall1(float8out,
- Float8GetDatum(num)));
-
- len = strlen(str) + VARHDRSZ;
-
- result = (text *) palloc(len);
-
- VARATT_SIZEP(result) = len;
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/*
- * text_float8 - converts a text string to a float8 number
- */
-Datum
-text_float8(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Datum result;
- int len;
- char *str;
-
- len = (VARSIZE(string) - VARHDRSZ);
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(float8in, CStringGetDatum(str));
-
- pfree(str);
-
- PG_RETURN_DATUM(result);
-}
-
-
-/*
- * float4_text - converts a float4 number to a text string
- */
-Datum
-float4_text(PG_FUNCTION_ARGS)
-{
- float4 num = PG_GETARG_FLOAT4(0);
- text *result;
- int len;
- char *str;
-
- str = DatumGetCString(DirectFunctionCall1(float4out,
- Float4GetDatum(num)));
-
- len = strlen(str) + VARHDRSZ;
-
- result = (text *) palloc(len);
-
- VARATT_SIZEP(result) = len;
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/*
- * text_float4 - converts a text string to a float4 number
- */
-Datum
-text_float4(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Datum result;
- int len;
- char *str;
-
- len = (VARSIZE(string) - VARHDRSZ);
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(float4in, CStringGetDatum(str));
-
- pfree(str);
-
- PG_RETURN_DATUM(result);
-}
-
-
-/*
- * =======================
- * RANDOM FLOAT8 OPERATORS
- * =======================
- */
-
-/*
- * dround - returns ROUND(arg1)
- */
-Datum
-dround(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- result = rint(arg1);
-
- 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
- */
-Datum
-dtrunc(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
- */
-Datum
-dsqrt(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- if (arg1 < 0)
- elog(ERROR, "can't take sqrt of a negative number");
-
- result = sqrt(arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dcbrt - returns cube root of arg1
- */
-Datum
-dcbrt(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- result = cbrt(arg1);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dpow - returns pow(arg1,arg2)
- */
-Datum
-dpow(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- /*
- * We must check both for errno getting set and for a NaN result, in
- * order to deal with the vagaries of different platforms...
- */
- errno = 0;
- result = pow(arg1, arg2);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "pow() result is out of range");
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dexp - returns the exponential function of arg1
- */
-Datum
-dexp(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- /*
- * 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.
- */
- errno = 0;
- result = exp(arg1);
- if (errno != 0 || result == 0.0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "exp() result is out of range");
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dlog1 - returns the natural logarithm of arg1
- * ("dlog" is already a logging routine...)
- */
-Datum
-dlog1(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- if (arg1 == 0.0)
- elog(ERROR, "can't take log of zero");
- if (arg1 < 0)
- elog(ERROR, "can't take log of a negative number");
-
- result = log(arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dlog10 - returns the base 10 logarithm of arg1
- */
-Datum
-dlog10(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- if (arg1 == 0.0)
- elog(ERROR, "can't take log of zero");
- if (arg1 < 0)
- elog(ERROR, "can't take log of a negative number");
-
- result = log10(arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dacos - returns the arccos of arg1 (radians)
- */
-Datum
-dacos(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = acos(arg1);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "acos(%f) input is out of range", arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dasin - returns the arcsin of arg1 (radians)
- */
-Datum
-dasin(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = asin(arg1);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "asin(%f) input is out of range", arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * datan - returns the arctan of arg1 (radians)
- */
-Datum
-datan(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = atan(arg1);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "atan(%f) input is out of range", arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * atan2 - returns the arctan2 of arg1 (radians)
- */
-Datum
-datan2(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
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "atan2(%f,%f) input is out of range", arg1, arg2);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dcos - returns the cosine of arg1 (radians)
- */
-Datum
-dcos(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = cos(arg1);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "cos(%f) input is out of range", arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dcot - returns the cotangent of arg1 (radians)
- */
-Datum
-dcot(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = tan(arg1);
- if (errno != 0 || result == 0.0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "cot(%f) input is out of range", arg1);
-
- result = 1.0 / result;
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dsin - returns the sine of arg1 (radians)
- */
-Datum
-dsin(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = sin(arg1);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "sin(%f) input is out of range", arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dtan - returns the tangent of arg1 (radians)
- */
-Datum
-dtan(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- errno = 0;
- result = tan(arg1);
- if (errno != 0
-#ifdef HAVE_FINITE
- || !finite(result)
-#endif
- )
- elog(ERROR, "tan(%f) input is out of range", arg1);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * degrees - returns degrees converted from radians
- */
-Datum
-degrees(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- result = arg1 * (180.0 / M_PI);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * dpi - returns the constant PI
- */
-Datum
-dpi(PG_FUNCTION_ARGS)
-{
- PG_RETURN_FLOAT8(M_PI);
-}
-
-
-/*
- * radians - returns radians converted from degrees
- */
-Datum
-radians(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float8 result;
-
- result = arg1 * (M_PI / 180.0);
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * drandom - returns a random number
- */
-Datum
-drandom(PG_FUNCTION_ARGS)
-{
- float8 result;
-
- /* result 0.0-1.0 */
- result = ((double) random()) / ((double) MAX_RANDOM_VALUE);
-
- PG_RETURN_FLOAT8(result);
-}
-
-
-/*
- * setseed - set seed for the random number generator
- */
-Datum
-setseed(PG_FUNCTION_ARGS)
-{
- float8 seed = PG_GETARG_FLOAT8(0);
- int iseed = (int) (seed * MAX_RANDOM_VALUE);
-
- srandom((unsigned int) iseed);
-
- PG_RETURN_INT32(iseed);
-}
-
-
-
-/*
- * =========================
- * FLOAT AGGREGATE OPERATORS
- * =========================
- *
- * float8_accum - accumulate for AVG(), STDDEV(), etc
- * float4_accum - same, but input data is float4
- * float8_avg - produce final result for float AVG()
- * float8_variance - produce final result for float VARIANCE()
- * float8_stddev - produce final result for float STDDEV()
- *
- * 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)
-{
- /*
- * We expect the input to be a 3-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 3 float8 values.
- */
- if (ARR_SIZE(transarray) != (ARR_OVERHEAD(1) + 3 * sizeof(float8)) ||
- ARR_NDIM(transarray) != 1 ||
- ARR_DIMS(transarray)[0] != 3)
- elog(ERROR, "%s: expected 3-element float8 array", caller);
- return (float8 *) ARR_DATA_PTR(transarray);
-}
-
-Datum
-float8_accum(PG_FUNCTION_ARGS)
-{
- ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
- float8 newval = PG_GETARG_FLOAT8(1);
- float8 *transvalues;
- float8 N,
- sumX,
- sumX2;
- Datum transdatums[3];
- ArrayType *result;
-
- transvalues = check_float8_array(transarray, "float8_accum");
- N = transvalues[0];
- sumX = transvalues[1];
- sumX2 = transvalues[2];
-
- N += 1.0;
- sumX += newval;
- sumX2 += newval * newval;
-
- transdatums[0] = Float8GetDatumFast(N);
- transdatums[1] = Float8GetDatumFast(sumX);
- transdatums[2] = Float8GetDatumFast(sumX2);
-
- result = construct_array(transdatums, 3,
- false /* float8 byval */ , sizeof(float8), 'd');
-
- PG_RETURN_ARRAYTYPE_P(result);
-}
-
-Datum
-float4_accum(PG_FUNCTION_ARGS)
-{
- ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
- float4 newval4 = PG_GETARG_FLOAT4(1);
- float8 *transvalues;
- float8 N,
- sumX,
- sumX2,
- newval;
- Datum transdatums[3];
- ArrayType *result;
-
- transvalues = check_float8_array(transarray, "float4_accum");
- N = transvalues[0];
- sumX = transvalues[1];
- sumX2 = transvalues[2];
-
- /* Do arithmetic in float8 for best accuracy */
- newval = newval4;
-
- N += 1.0;
- sumX += newval;
- sumX2 += newval * newval;
-
- transdatums[0] = Float8GetDatumFast(N);
- transdatums[1] = Float8GetDatumFast(sumX);
- transdatums[2] = Float8GetDatumFast(sumX2);
-
- result = construct_array(transdatums, 3,
- false /* float8 byval */ , sizeof(float8), 'd');
-
- PG_RETURN_ARRAYTYPE_P(result);
-}
-
-Datum
-float8_avg(PG_FUNCTION_ARGS)
-{
- ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
- float8 *transvalues;
- float8 N,
- sumX;
-
- transvalues = check_float8_array(transarray, "float8_avg");
- 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);
-}
-
-Datum
-float8_variance(PG_FUNCTION_ARGS)
-{
- ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
- float8 *transvalues;
- float8 N,
- sumX,
- sumX2,
- numerator;
-
- transvalues = check_float8_array(transarray, "float8_variance");
- N = transvalues[0];
- sumX = transvalues[1];
- sumX2 = transvalues[2];
-
- /* We define VARIANCE of no values to be NULL, of 1 value to be 0 */
- if (N == 0.0)
- PG_RETURN_NULL();
-
- if (N <= 1.0)
- PG_RETURN_FLOAT8(0.0);
-
- numerator = N * sumX2 - sumX * sumX;
-
- /* 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)));
-}
-
-Datum
-float8_stddev(PG_FUNCTION_ARGS)
-{
- ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
- float8 *transvalues;
- float8 N,
- sumX,
- sumX2,
- numerator;
-
- transvalues = check_float8_array(transarray, "float8_stddev");
- N = transvalues[0];
- sumX = transvalues[1];
- sumX2 = transvalues[2];
-
- /* We define STDDEV of no values to be NULL, of 1 value to be 0 */
- if (N == 0.0)
- PG_RETURN_NULL();
-
- if (N <= 1.0)
- PG_RETURN_FLOAT8(0.0);
-
- numerator = N * sumX2 - sumX * sumX;
-
- /* 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))));
-}
-
-
-/*
- * ====================================
- * MIXED-PRECISION ARITHMETIC OPERATORS
- * ====================================
- */
-
-/*
- * float48pl - returns arg1 + arg2
- * float48mi - returns arg1 - arg2
- * float48mul - returns arg1 * arg2
- * float48div - returns arg1 / arg2
- */
-Datum
-float48pl(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = arg1 + arg2;
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float48mi(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = arg1 - arg2;
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float48mul(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- result = arg1 * arg2;
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float48div(PG_FUNCTION_ARGS)
-{
- float4 arg1 = PG_GETARG_FLOAT4(0);
- float8 arg2 = PG_GETARG_FLOAT8(1);
- float8 result;
-
- if (arg2 == 0.0)
- elog(ERROR, "float48div: divide by zero");
-
- result = arg1 / arg2;
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-/*
- * float84pl - returns arg1 + arg2
- * float84mi - returns arg1 - arg2
- * float84mul - returns arg1 * arg2
- * float84div - returns arg1 / arg2
- */
-Datum
-float84pl(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- float8 result;
-
- result = arg1 + arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float84mi(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- float8 result;
-
- result = arg1 - arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float84mul(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- float8 result;
-
- result = arg1 * arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-Datum
-float84div(PG_FUNCTION_ARGS)
-{
- float8 arg1 = PG_GETARG_FLOAT8(0);
- float4 arg2 = PG_GETARG_FLOAT4(1);
- float8 result;
-
- if (arg2 == 0.0)
- elog(ERROR, "float84div: divide by zero");
-
- result = arg1 / arg2;
-
- CheckFloat8Val(result);
- PG_RETURN_FLOAT8(result);
-}
-
-/*
- * ====================
- * COMPARISON OPERATORS
- * ====================
- */
-
-/*
- * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
- */
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-/*
- * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
- */
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-Datum
-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);
-}
-
-/* ========== PRIVATE ROUTINES ========== */
-
-/* From "fdlibm" @ netlib.att.com */
-
-#ifndef HAVE_RINT
-
-/* @(#)s_rint.c 5.1 93/09/24 */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-/*
- * rint(x)
- * Return x rounded to integral value according to the prevailing
- * rounding mode.
- * Method:
- * Using floating addition.
- * Exception:
- * Inexact flag raised if x not equal to rint(x).
- */
-
-static const double one = 1.0,
- TWO52[2] = {
- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
-};
-
-static double
-rint(double x)
-{
- int i0,
- n0,
- j0,
- sx;
- unsigned i,
- i1;
- double w,
- t;
-
- n0 = (*((int *) &one) >> 29) ^ 1;
- i0 = *(n0 + (int *) &x);
- sx = (i0 >> 31) & 1;
- i1 = *(1 - n0 + (int *) &x);
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- if (j0 < 20)
- {
- if (j0 < 0)
- {
- if (((i0 & 0x7fffffff) | i1) == 0)
- return x;
- i1 |= (i0 & 0x0fffff);
- i0 &= 0xfffe0000;
- i0 |= ((i1 | -i1) >> 12) & 0x80000;
- *(n0 + (int *) &x) = i0;
- w = TWO52[sx] + x;
- t = w - TWO52[sx];
- i0 = *(n0 + (int *) &t);
- *(n0 + (int *) &t) = (i0 & 0x7fffffff) | (sx << 31);
- return t;
- }
- else
- {
- i = (0x000fffff) >> j0;
- if (((i0 & i) | i1) == 0)
- return x; /* x is integral */
- i >>= 1;
- if (((i0 & i) | i1) != 0)
- {
- if (j0 == 19)
- i1 = 0x40000000;
- else
- i0 = (i0 & (~i)) | ((0x20000) >> j0);
- }
- }
- }
- else if (j0 > 51)
- {
- if (j0 == 0x400)
- return x + x; /* inf or NaN */
- else
- return x; /* x is integral */
- }
- else
- {
- i = ((unsigned) (0xffffffff)) >> (j0 - 20);
- if ((i1 & i) == 0)
- return x; /* x is integral */
- i >>= 1;
- if ((i1 & i) != 0)
- i1 = (i1 & (~i)) | ((0x40000000) >> (j0 - 20));
- }
- *(n0 + (int *) &x) = i0;
- *(1 - n0 + (int *) &x) = i1;
- w = TWO52[sx] + x;
- return w - TWO52[sx];
-}
-#endif /* !HAVE_RINT */
-
-#ifndef HAVE_CBRT
-
-static double
-cbrt(double x)
-{
- int isneg = (x < 0.0);
- double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
-
- return isneg ? -tmpres : tmpres;
-}
-
-#endif /* !HAVE_CBRT */