float.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:27k
- /*-------------------------------------------------------------------------
- *
- * float.c
- * Functions for the built-in floating-point types.
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.42.2.1 1999/08/02 05:24:52 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, 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 converting...)
- *
- * 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 <ctype.h>
- #include <errno.h>
- #include <float.h> /* faked on sunos4 */
- #include <math.h>
- #include "postgres.h"
- #ifdef HAVE_LIMITS_H
- #include <limits.h>
- #endif
- #include "fmgr.h"
- #include "utils/builtins.h"
- #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
- #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
- #ifndef HAVE_RINT
- #define rint my_rint
- static double rint(double x);
- #else
- extern double rint(double x);
- #endif
- #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
- /*
- * if FLOAT8_MIN and FLOAT8_MAX are the limits of the range a
- * double can store, then how are we ever going to wind up
- * with something stored in a double that is outside those
- * limits? (and similarly for FLOAT4_{MIN,MAX}/float.)
- * doesn't make sense to me, and it causes a
- * floating point exception on linuxalpha, so UNSAFE_FLOATS
- * it is.
- * (maybe someone wanted to allow for values other than DBL_MIN/
- * DBL_MAX for FLOAT8_MIN/FLOAT8_MAX?)
- * --djm 12/12/96
- * according to Richard Henderson this is a known bug in gcc on
- * the Alpha. might as well leave the workaround in
- * until the distributions are updated.
- * --djm 12/16/96
- */
- #if ( defined(linux) && defined(__alpha__) ) && !defined(UNSAFE_FLOATS)
- #define UNSAFE_FLOATS
- #endif
- /*
- 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
- */
- 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.
- */
- float32
- float4in(char *num)
- {
- float32 result = (float32) palloc(sizeof(float32data));
- double val;
- char *endptr;
- errno = 0;
- val = strtod(num, &endptr);
- if (*endptr != ' ')
- {
- /* Should we accept "NaN" or "Infinity" for float4? */
- 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);
- *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 != ' ')
- {
- if (strcasecmp(num, "NaN") == 0)
- val = NAN;
- 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);
- *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)");
- if (isnan(*num))
- return strcpy(ascii, "NaN");
- if (isinf(*num))
- return strcpy(ascii, "Infinity");
- 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 != 0) ? -(*arg1) : *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 != 0) ? -(*arg1) : *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(ERROR, "float4div: divide by zero 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(ERROR, "float8div: divide by zero 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
- */
- bool
- float4eq(float32 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 == *arg2;
- }
- bool
- float4ne(float32 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 != *arg2;
- }
- bool
- float4lt(float32 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 < *arg2;
- }
- bool
- float4le(float32 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 <= *arg2;
- }
- bool
- float4gt(float32 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 > *arg2;
- }
- bool
- float4ge(float32 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 >= *arg2;
- }
- /*
- * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
- */
- bool
- float8eq(float64 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 == *arg2;
- }
- bool
- float8ne(float64 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 != *arg2;
- }
- bool
- float8lt(float64 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 < *arg2;
- }
- bool
- float8le(float64 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 <= *arg2;
- }
- bool
- float8gt(float64 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 > *arg2;
- }
- bool
- float8ge(float64 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- 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;
- CheckFloat4Val(*num);
- result = (float32) palloc(sizeof(float32data));
- *result = *num;
- return result;
- }
- /*
- * dtoi4 - converts a float8 number to an int4 number
- */
- int32
- dtoi4(float64 num)
- {
- int32 result;
- if (!PointerIsValid(num))
- elog(ERROR, "dtoi4: unable to convert null", NULL);
- if ((*num < INT_MIN) || (*num > INT_MAX))
- elog(ERROR, "dtoi4: integer out of range", NULL);
- result = rint(*num);
- return result;
- }
- /*
- * dtoi2 - converts a float8 number to an int2 number
- */
- int16
- dtoi2(float64 num)
- {
- int16 result;
- if (!PointerIsValid(num))
- elog(ERROR, "dtoi2: unable to convert null", NULL);
- if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
- elog(ERROR, "dtoi2: integer out of range", NULL);
- result = rint(*num);
- return result;
- }
- /*
- * i4tod - converts an int4 number to a float8 number
- */
- float64
- i4tod(int32 num)
- {
- float64 result;
- result = (float64) palloc(sizeof(float64data));
- *result = num;
- return result;
- }
- /*
- * i2tod - converts an int2 number to a float8 number
- */
- float64
- i2tod(int16 num)
- {
- float64 result;
- result = (float64) palloc(sizeof(float64data));
- *result = num;
- return result;
- }
- /*
- * ftoi4 - converts a float8 number to an int4 number
- */
- int32
- ftoi4(float32 num)
- {
- int32 result;
- if (!PointerIsValid(num))
- elog(ERROR, "ftoi4: unable to convert null", NULL);
- if ((*num < INT_MIN) || (*num > INT_MAX))
- elog(ERROR, "ftoi4: integer out of range", NULL);
- result = rint(*num);
- return result;
- }
- /*
- * ftoi2 - converts a float8 number to an int2 number
- */
- int16
- ftoi2(float32 num)
- {
- int16 result;
- if (!PointerIsValid(num))
- elog(ERROR, "ftoi2: unable to convert null", NULL);
- if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
- elog(ERROR, "ftoi2: integer out of range", NULL);
- result = rint(*num);
- return result;
- }
- /*
- * i4tof - converts an int4 number to a float8 number
- */
- float32
- i4tof(int32 num)
- {
- float32 result;
- result = (float32) palloc(sizeof(float32data));
- *result = num;
- return result;
- }
- /*
- * i2tof - converts an int2 number to a float8 number
- */
- float32
- i2tof(int16 num)
- {
- float32 result;
- result = (float32) palloc(sizeof(float32data));
- *result = num;
- return result;
- }
- /*
- * float8_text - converts a float8 number to a text string
- */
- text *
- float8_text(float64 num)
- {
- text *result;
- int len;
- char *str;
- str = float8out(num);
- len = (strlen(str) + VARHDRSZ);
- result = palloc(len);
- VARSIZE(result) = len;
- memmove(VARDATA(result), str, (len - VARHDRSZ));
- pfree(str);
- return result;
- } /* float8_text() */
- /*
- * text_float8 - converts a text string to a float8 number
- */
- float64
- text_float8(text *string)
- {
- float64 result;
- int len;
- char *str;
- len = (VARSIZE(string) - VARHDRSZ);
- str = palloc(len + 1);
- memmove(str, VARDATA(string), len);
- *(str + len) = ' ';
- result = float8in(str);
- pfree(str);
- return result;
- } /* text_float8() */
- /*
- * float4_text - converts a float4 number to a text string
- */
- text *
- float4_text(float32 num)
- {
- text *result;
- int len;
- char *str;
- str = float4out(num);
- len = (strlen(str) + VARHDRSZ);
- result = palloc(len);
- VARSIZE(result) = len;
- memmove(VARDATA(result), str, (len - VARHDRSZ));
- pfree(str);
- return result;
- } /* float4_text() */
- /*
- * text_float4 - converts a text string to a float4 number
- */
- float32
- text_float4(text *string)
- {
- float32 result;
- int len;
- char *str;
- len = (VARSIZE(string) - VARHDRSZ);
- str = palloc(len + 1);
- memmove(str, VARDATA(string), len);
- *(str + len) = ' ';
- result = float4in(str);
- pfree(str);
- return result;
- } /* text_float4() */
- /*
- * =======================
- * 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;
- #ifndef finite
- errno = 0;
- #endif
- *result = (float64data) pow(tmp1, tmp2);
- #ifndef finite
- if (errno != 0) /* on some machines both EDOM & ERANGE can
- * occur */
- #else
- if (!finite(*result))
- #endif
- elog(ERROR, "pow() result is out of range");
- 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;
- #ifndef finite
- errno = 0;
- #endif
- *result = (float64data) exp(tmp);
- #ifndef finite
- if (errno == ERANGE)
- #else
- /* infinity implies overflow, zero implies underflow */
- if (!finite(*result) || *result == 0.0)
- #endif
- elog(ERROR, "exp() result is out of range");
- 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(ERROR, "can't take log of zero");
- if (tmp < 0)
- elog(ERROR, "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(ERROR, "float48div: divide by zero");
- *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(ERROR, "float48div: divide by zero");
- *result = *arg1 / *arg2;
- CheckFloat8Val(*result);
- return result;
- }
- /*
- * ====================
- * COMPARISON OPERATORS
- * ====================
- */
- /*
- * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
- */
- bool
- float48eq(float32 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 == (float) *arg2;
- }
- bool
- float48ne(float32 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 != (float) *arg2;
- }
- bool
- float48lt(float32 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 < (float) *arg2;
- }
- bool
- float48le(float32 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 <= (float) *arg2;
- }
- bool
- float48gt(float32 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 > (float) *arg2;
- }
- bool
- float48ge(float32 arg1, float64 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return *arg1 >= (float) *arg2;
- }
- /*
- * float84{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
- */
- bool
- float84eq(float64 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return (float) *arg1 == *arg2;
- }
- bool
- float84ne(float64 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return (float) *arg1 != *arg2;
- }
- bool
- float84lt(float64 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return (float) *arg1 < *arg2;
- }
- bool
- float84le(float64 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return (float) *arg1 <= *arg2;
- }
- bool
- float84gt(float64 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return (float) *arg1 > *arg2;
- }
- bool
- float84ge(float64 arg1, float32 arg2)
- {
- if (!arg1 || !arg2)
- return 0;
- return (float) *arg1 >= *arg2;
- }
- /* ========== 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).
- */
- #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 /* !HAVE_RINT */
- #ifndef HAVE_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 /* !HAVE_CBRT */