aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/float.c
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
committerMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
commitd31084e9d1118b25fd16580d9d8c2924b5740dff (patch)
tree3179e66307d54df9c7b966543550e601eb55e668 /src/backend/utils/adt/float.c
downloadpostgresql-d31084e9d1118b25fd16580d9d8c2924b5740dff.tar.gz
postgresql-d31084e9d1118b25fd16580d9d8c2924b5740dff.zip
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r--src/backend/utils/adt/float.c1320
1 files changed, 1320 insertions, 0 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
new file mode 100644
index 00000000000..ef962e71368
--- /dev/null
+++ b/src/backend/utils/adt/float.c
@@ -0,0 +1,1320 @@
+/*-------------------------------------------------------------------------
+ *
+ * float.c--
+ * Functions for the built-in floating-point types.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.1.1.1 1996/07/09 06:22:04 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ * OLD COMMENTS
+ * Basic float4 ops:
+ * float4in, float4out, float4abs, float4um
+ * Basic float8 ops:
+ * float8in, float8inAd, float8out, float8outAd, float8abs, float8um
+ * Arithmetic operators:
+ * float4pl, float4mi, float4mul, float4div
+ * float8pl, float8mi, float8mul, float8div
+ * Comparison operators:
+ * float4eq, float4ne, float4lt, float4le, float4gt, float4ge
+ * float8eq, float8ne, float8lt, float8le, float8gt, float8ge
+ * Conversion routines:
+ * ftod, dtof
+ *
+ * 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 converting...)
+ *
+ * XXX GLUESOME STUFF. FIX IT! -AY '94
+ */
+#include <stdio.h> /* for sprintf() */
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <float.h> /* faked on sunos4 */
+
+#include <math.h>
+
+#include "postgres.h"
+#include "fmgr.h"
+#include "utils/builtins.h" /* for ftod() prototype */
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+
+#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
+
+#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
+
+#ifdef NEED_CBRT
+#define cbrt my_cbrt
+static double cbrt(double x);
+#else /* NEED_CBRT */
+extern double cbrt(double x);
+#endif /* NEED_CBRT */
+
+#ifdef NEED_RINT
+#define rint my_rint
+static double rint(double x);
+#else /* NEED_RINT */
+extern double rint(double x);
+#endif /* NEED_RINT */
+
+#ifdef NEED_ISINF
+#define isinf my_isinf
+static int isinf(double x);
+#else /* NEED_ISINF */
+extern int isinf(double x);
+#endif /* NEED_ISINF */
+
+#endif
+/* ========== 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(WARN,"\tBad float4 input format -- overflow\n");
+ if (val != 0.0 && fabs(val) < FLOAT4_MIN)
+ elog(WARN,"\tBad float4 input format -- underflow\n");
+ 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(WARN,"\tBad float8 input format -- overflow\n");
+ if (val != 0.0 && fabs(val) < FLOAT8_MIN)
+ elog(WARN,"\tBad float8 input format -- underflow\n");
+ 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.
+ */
+float32 float4in(char *num)
+{
+ float32 result = (float32) palloc(sizeof(float32data));
+ double val;
+ char* endptr;
+
+ errno = 0;
+ val = strtod(num,&endptr);
+ if (*endptr != '\0' || errno == ERANGE)
+ elog(WARN,"\tBad float4 input format\n");
+
+ /* if we get here, we have a legal double, still need to check to see
+ if it's a legal float */
+
+ CheckFloat4Val(val);
+
+ *result = val;
+ return result;
+}
+
+/*
+ * float4out - converts a float4 number to a string
+ * using a standard output format
+ */
+char *float4out(float32 num)
+{
+ char *ascii = (char *)palloc(MAXFLOATWIDTH+1);
+
+ if (!num)
+ return strcpy(ascii, "(null)");
+
+ sprintf(ascii, "%.*g", FLT_DIG, *num);
+ return(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.
+ */
+float64 float8in(char *num)
+{
+ float64 result = (float64) palloc(sizeof(float64data));
+ double val;
+ char* endptr;
+
+ errno = 0;
+ val = strtod(num,&endptr);
+ if (*endptr != '\0' || errno == ERANGE)
+ elog(WARN,"\tBad float8 input format\n");
+
+ CheckFloat8Val(val);
+ *result = val;
+ return(result);
+}
+
+
+/*
+ * float8out - converts float8 number to a string
+ * using a standard output format
+ */
+char *float8out(float64 num)
+{
+ char *ascii = (char *)palloc(MAXDOUBLEWIDTH+1);
+
+ if (!num)
+ return strcpy(ascii, "(null)");
+
+#ifndef WIN32
+ if (isnan(*num))
+ return strcpy(ascii, "NaN");
+ if (isinf(*num))
+ return strcpy(ascii, "Infinity");
+#else
+ if (_isnan(*num))
+ return strcpy(ascii, "NaN");
+ if (!_finite(*num))
+ return strcpy(ascii, "Infinity");
+#endif
+
+ sprintf(ascii, "%.*g", DBL_DIG, *num);
+ return(ascii);
+}
+
+/* ========== PUBLIC ROUTINES ========== */
+
+
+/*
+ * ======================
+ * FLOAT4 BASE OPERATIONS
+ * ======================
+ */
+
+/*
+ * float4abs - returns a pointer to |arg1| (absolute value)
+ */
+float32 float4abs(float32 arg1)
+{
+ float32 result;
+ double val;
+
+ if (!arg1)
+ return (float32)NULL;
+
+ val = fabs(*arg1);
+
+ CheckFloat4Val(val);
+
+ result = (float32) palloc(sizeof(float32data));
+ *result = val;
+ return(result);
+}
+
+/*
+ * float4um - returns a pointer to -arg1 (unary minus)
+ */
+float32 float4um(float32 arg1)
+{
+ float32 result;
+ double val;
+
+ if (!arg1)
+ return (float32)NULL;
+
+ val = -(*arg1);
+ CheckFloat4Val(val);
+
+ result = (float32) palloc(sizeof(float32data));
+ *result = val;
+ return(result);
+}
+
+float32 float4larger(float32 arg1, float32 arg2)
+{
+ float32 result;
+
+ if (!arg1 || !arg2)
+ return (float32)NULL;
+
+ result = (float32) palloc(sizeof(float32data));
+
+ *result = ((*arg1 > *arg2) ? *arg1 : *arg2);
+ return result;
+}
+
+float32 float4smaller(float32 arg1, float32 arg2)
+{
+ float32 result;
+
+ if (!arg1 || !arg2)
+ return (float32)NULL;
+
+ result = (float32) palloc(sizeof(float32data));
+
+ *result = ((*arg1 > *arg2) ? *arg2 : *arg1);
+ return result;
+}
+
+/*
+ * ======================
+ * FLOAT8 BASE OPERATIONS
+ * ======================
+ */
+
+/*
+ * float8abs - returns a pointer to |arg1| (absolute value)
+ */
+float64 float8abs(float64 arg1)
+{
+ float64 result;
+ double val;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ val = fabs(*arg1);
+ CheckFloat8Val(val);
+ *result = val;
+ return(result);
+}
+
+
+/*
+ * float8um - returns a pointer to -arg1 (unary minus)
+ */
+float64 float8um(float64 arg1)
+{
+ float64 result;
+ double val;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ val = -(*arg1);
+
+ CheckFloat8Val(val);
+ result = (float64) palloc(sizeof(float64data));
+ *result = val;
+ return(result);
+}
+
+float64 float8larger(float64 arg1, float64 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = ((*arg1 > *arg2) ? *arg1 : *arg2);
+ return result;
+}
+
+float64 float8smaller(float64 arg1, float64 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = ((*arg1 > *arg2) ? *arg2 : *arg1);
+ return result;
+}
+
+
+/*
+ * ====================
+ * ARITHMETIC OPERATORS
+ * ====================
+ */
+
+/*
+ * float4pl - returns a pointer to arg1 + arg2
+ * float4mi - returns a pointer to arg1 - arg2
+ * float4mul - returns a pointer to arg1 * arg2
+ * float4div - returns a pointer to arg1 / arg2
+ * float4inc - returns a poniter to arg1 + 1.0
+ */
+float32 float4pl(float32 arg1, float32 arg2)
+{
+ float32 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float32)NULL;
+
+ val = *arg1 + *arg2;
+ CheckFloat4Val(val);
+
+ result = (float32) palloc(sizeof(float32data));
+ *result = val;
+
+ return(result);
+}
+
+float32 float4mi(float32 arg1, float32 arg2)
+{
+ float32 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float32)NULL;
+
+ val = *arg1 - *arg2;
+
+ CheckFloat4Val(val);
+ result = (float32) palloc(sizeof(float32data));
+ *result = val;
+ return(result);
+}
+
+float32 float4mul(float32 arg1, float32 arg2)
+{
+ float32 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float32)NULL;
+
+ val = *arg1 * *arg2;
+
+ CheckFloat4Val(val);
+ result = (float32) palloc(sizeof(float32data));
+ *result = val;
+ return(result);
+}
+
+float32 float4div(float32 arg1, float32 arg2)
+{
+ float32 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float32)NULL;
+
+ if (*arg2 == 0.0)
+ elog(WARN,"float4div: divide by 0.0 error");
+
+ val = *arg1 / *arg2;
+
+ CheckFloat4Val(val);
+ result = (float32) palloc(sizeof(float32data));
+ *result = *arg1 / *arg2;
+ return(result);
+}
+
+float32 float4inc(float32 arg1)
+{
+ double val;
+
+ if (!arg1)
+ return (float32)NULL;
+
+ val = *arg1 + (float32data)1.0;
+ CheckFloat4Val(val);
+ *arg1 = val;
+ return arg1;
+}
+
+/*
+ * float8pl - returns a pointer to arg1 + arg2
+ * float8mi - returns a pointer to arg1 - arg2
+ * float8mul - returns a pointer to arg1 * arg2
+ * float8div - returns a pointer to arg1 / arg2
+ * float8inc - returns a pointer to arg1 + 1.0
+ */
+float64 float8pl(float64 arg1, float64 arg2)
+{
+ float64 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ val = *arg1 + *arg2;
+ CheckFloat8Val(val);
+ *result = val;
+ return(result);
+}
+
+float64 float8mi(float64 arg1, float64 arg2)
+{
+ float64 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ val = *arg1 - *arg2;
+ CheckFloat8Val(val);
+ *result = val;
+ return(result);
+}
+
+float64 float8mul(float64 arg1, float64 arg2)
+{
+ float64 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ val = *arg1 * *arg2;
+ CheckFloat8Val(val);
+ *result = val;
+ return(result);
+}
+
+float64 float8div(float64 arg1, float64 arg2)
+{
+ float64 result;
+ double val;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ if (*arg2 == 0.0)
+ elog(WARN,"float8div: divide by 0.0 error");
+
+ val = *arg1 / *arg2;
+ CheckFloat8Val(val);
+ *result = val;
+ return(result);
+}
+
+float64 float8inc(float64 arg1)
+{
+ double val;
+ if (!arg1)
+ return (float64)NULL;
+
+ val = *arg1 + (float64data)1.0;
+ CheckFloat8Val(val);
+ *arg1 = val;
+ return(arg1);
+}
+
+
+/*
+ * ====================
+ * COMPARISON OPERATORS
+ * ====================
+ */
+
+/*
+ * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
+ */
+long float4eq(float32 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 == *arg2);
+}
+
+long float4ne(float32 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 != *arg2);
+}
+
+long float4lt(float32 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 < *arg2);
+}
+
+long float4le(float32 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 <= *arg2);
+}
+
+long float4gt(float32 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 > *arg2);
+}
+
+long float4ge(float32 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 >= *arg2);
+}
+
+/*
+ * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
+ */
+long float8eq(float64 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 == *arg2);
+}
+
+long float8ne(float64 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 != *arg2);
+}
+
+long float8lt(float64 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 < *arg2);
+}
+
+long float8le(float64 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 <= *arg2);
+}
+
+long float8gt(float64 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 > *arg2);
+}
+
+long float8ge(float64 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 >= *arg2);
+}
+
+
+/*
+ * ===================
+ * CONVERSION ROUTINES
+ * ===================
+ */
+
+/*
+ * ftod - converts a float4 number to a float8 number
+ */
+float64 ftod(float32 num)
+{
+ float64 result;
+
+ if (!num)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *num;
+ return(result);
+}
+
+
+/*
+ * dtof - converts a float8 number to a float4 number
+ */
+float32 dtof(float64 num)
+{
+ float32 result;
+
+ if (!num)
+ return (float32)NULL;
+
+ result = (float32) palloc(sizeof(float32data));
+
+ *result = *num;
+ return(result);
+}
+
+
+/*
+ * =======================
+ * RANDOM FLOAT8 OPERATORS
+ * =======================
+ */
+
+/*
+ * dround - returns a pointer to ROUND(arg1)
+ */
+float64 dround(float64 arg1)
+{
+ float64 result;
+ double tmp;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp = *arg1;
+ *result = (float64data) rint(tmp);
+ return(result);
+}
+
+
+/*
+ * dtrunc - returns a pointer to truncation of arg1,
+ * arg1 >= 0 ... the greatest integer as float8 less
+ * than or equal to arg1
+ * arg1 < 0 ... the greatest integer as float8 greater
+ * than or equal to arg1
+ */
+float64 dtrunc(float64 arg1)
+{
+ float64 result;
+ double tmp;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp = *arg1;
+ if (*arg1 >= 0)
+ *result = (float64data) floor(tmp);
+ else
+ *result = (float64data) -(floor(-tmp));
+ return(result);
+}
+
+
+/*
+ * dsqrt - returns a pointer to square root of arg1
+ */
+float64 dsqrt(float64 arg1)
+{
+ float64 result;
+ double tmp;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp = *arg1;
+ *result = (float64data) sqrt(tmp);
+ return (result);
+}
+
+
+/*
+ * dcbrt - returns a pointer to cube root of arg1
+ */
+float64 dcbrt(float64 arg1)
+{
+ float64 result;
+ double tmp;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp = *arg1;
+ *result = (float64data) cbrt(tmp);
+ return(result);
+}
+
+
+/*
+ * dpow - returns a pointer to pow(arg1,arg2)
+ */
+float64 dpow(float64 arg1, float64 arg2)
+{
+ float64 result;
+ double tmp1, tmp2;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp1 = *arg1;
+ tmp2 = *arg2;
+ errno = 0;
+ *result = (float64data) pow(tmp1, tmp2);
+ if (errno == ERANGE)
+ elog(WARN, "pow() returned a floating point out of the range\n");
+
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+
+/*
+ * dexp - returns a pointer to the exponential function of arg1
+ */
+float64 dexp(float64 arg1)
+{
+ float64 result;
+ double tmp;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp = *arg1;
+ errno = 0;
+ *result = (float64data) exp(tmp);
+ if (errno == ERANGE)
+ elog(WARN, "exp() returned a floating point out of range\n");
+
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+
+/*
+ * dlog1 - returns a pointer to the natural logarithm of arg1
+ * ("dlog" is already a logging routine...)
+ */
+float64 dlog1(float64 arg1)
+{
+ float64 result;
+ double tmp;
+
+ if (!arg1)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ tmp = *arg1;
+ if (tmp == 0.0)
+ elog(WARN, "can't take log of 0!");
+ if (tmp < 0)
+ elog(WARN, "can't take log of a negative number");
+ *result = (float64data) log(tmp);
+
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+
+/*
+ * ====================
+ * ARITHMETIC OPERATORS
+ * ====================
+ */
+
+/*
+ * float48pl - returns a pointer to arg1 + arg2
+ * float48mi - returns a pointer to arg1 - arg2
+ * float48mul - returns a pointer to arg1 * arg2
+ * float48div - returns a pointer to arg1 / arg2
+ */
+float64 float48pl(float32 arg1, float64 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *arg1 + *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+float64 float48mi(float32 arg1, float64 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *arg1 - *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+float64 float48mul(float32 arg1, float64 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *arg1 * *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+float64 float48div(float32 arg1, float64 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ if (*arg2 == 0.0)
+ elog(WARN, "float48div: divide by 0.0 error!");
+
+ *result = *arg1 / *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+/*
+ * float84pl - returns a pointer to arg1 + arg2
+ * float84mi - returns a pointer to arg1 - arg2
+ * float84mul - returns a pointer to arg1 * arg2
+ * float84div - returns a pointer to arg1 / arg2
+ */
+float64 float84pl(float64 arg1, float32 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *arg1 + *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+float64 float84mi(float64 arg1, float32 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *arg1 - *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+float64 float84mul(float64 arg1, float32 arg2)
+{
+
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ *result = *arg1 * *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+float64 float84div(float64 arg1, float32 arg2)
+{
+ float64 result;
+
+ if (!arg1 || !arg2)
+ return (float64)NULL;
+
+ result = (float64) palloc(sizeof(float64data));
+
+ if (*arg2 == 0.0)
+ elog(WARN, "float48div: divide by 0.0 error!");
+
+ *result = *arg1 / *arg2;
+ CheckFloat8Val(*result);
+ return(result);
+}
+
+/*
+ * ====================
+ * COMPARISON OPERATORS
+ * ====================
+ */
+
+/*
+ * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
+ */
+long float48eq(float32 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 == (float)*arg2);
+}
+
+long float48ne(float32 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 != (float)*arg2);
+}
+
+long float48lt(float32 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 < (float)*arg2);
+}
+
+long float48le(float32 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 <= (float)*arg2);
+}
+
+long float48gt(float32 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 > (float)*arg2);
+}
+
+long float48ge(float32 arg1, float64 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return(*arg1 >= (float)*arg2);
+}
+
+/*
+ * float84{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
+ */
+long float84eq(float64 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return((float)*arg1 == *arg2);
+}
+
+long float84ne(float64 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return((float)*arg1 != *arg2);
+}
+
+long float84lt(float64 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return((float)*arg1 < *arg2);
+}
+
+long float84le(float64 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return((float)*arg1 <= *arg2);
+}
+
+long float84gt(float64 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return((float)*arg1 > *arg2);
+}
+
+long float84ge(float64 arg1, float32 arg2)
+{
+ if (!arg1 || !arg2)
+ return (long)NULL;
+
+ return((float)*arg1 >= *arg2);
+}
+
+/* ========== PRIVATE ROUTINES ========== */
+
+/* From "fdlibm" @ netlib.att.com */
+
+#ifdef NEED_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).
+ */
+
+#ifdef __STDC__
+static const double
+#else
+ static double
+#endif
+ one = 1.0,
+ TWO52[2]={
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+ };
+
+#ifdef __STDC__
+static double rint(double x)
+#else
+ static double rint(x)
+ double x;
+#endif
+{
+ 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 /* NEED_RINT */
+
+#ifdef NEED_CBRT
+
+static
+ double
+ cbrt(x)
+double x;
+{
+ int isneg = (x < 0.0);
+ double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
+
+ return(isneg ? -tmpres : tmpres);
+}
+
+#endif /* NEED_CBRT */
+
+#ifdef NEED_ISINF
+
+#if defined(PORTNAME_aix)
+#ifdef CLASS_CONFLICT
+/* we want the math symbol */
+#undef class
+#endif /* CLASS_CONFICT */
+
+static int isinf(x)
+ double x;
+{
+ int fpclass = class(x);
+ if (fpclass == FP_PLUS_INF)
+ return(1);
+ if (fpclass == FP_MINUS_INF)
+ return(-1);
+ return(0);
+}
+#endif /* PORTNAME_aix */
+
+#if defined(PORTNAME_ultrix4)
+#include <fp_class.h>
+static int isinf(x)
+ double x;
+{
+ int fpclass = fp_class_d(x);
+ if (fpclass == FP_POS_INF)
+ return(1);
+ if (fpclass == FP_NEG_INF)
+ return(-1);
+ return(0);
+}
+#endif /* PORTNAME_ultrix4 */
+
+#if defined(PORTNAME_alpha)
+#include <fp_class.h>
+static int isinf(x)
+ double x;
+{
+ int fpclass = fp_class(x);
+ if (fpclass == FP_POS_INF)
+ return(1);
+ if (fpclass == FP_NEG_INF)
+ return(-1);
+ return(0);
+}
+#endif /* PORTNAME_alpha */
+
+#if defined(PORTNAME_sparc_solaris)
+#include <ieeefp.h>
+static int
+ isinf(d)
+double d;
+{
+ fpclass_t type = fpclass(d);
+ switch (type) {
+ case FP_SNAN:
+ case FP_QNAN:
+ case FP_NINF:
+ case FP_PINF:
+ return (1);
+ default:
+ break;
+ }
+
+ return (0);
+}
+#endif /* PORTNAME_sparc_solaris */
+
+#if defined(PORTNAME_irix5)
+#include <ieeefp.h>
+static int
+ isinf(d)
+double d;
+{
+ fpclass_t type = fpclass(d);
+ switch (type) {
+ case FP_SNAN:
+ case FP_QNAN:
+ case FP_NINF:
+ case FP_PINF:
+ return (1);
+ default:
+ break;
+ }
+
+ return (0);
+}
+#endif /* PORTNAME_irix5 */
+
+#endif /* NEED_ISINF */