1 /*-------------------------------------------------------------------------
4 * Functions for the built-in floating-point types.
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.53 2000/01/26 05:57:14 momjian Exp $
13 *-------------------------------------------------------------------------
18 * float4in, float4out, float4abs, float4um
20 * float8in, float8inAd, float8out, float8outAd, float8abs, float8um
21 * Arithmetic operators:
22 * float4pl, float4mi, float4mul, float4div
23 * float8pl, float8mi, float8mul, float8div
24 * Comparison operators:
25 * float4eq, float4ne, float4lt, float4le, float4gt, float4ge
26 * float8eq, float8ne, float8lt, float8le, float8gt, float8ge
27 * Conversion routines:
28 * ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
31 * dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
32 * Arithmetic operators:
33 * float48pl, float48mi, float48mul, float48div
34 * float84pl, float84mi, float84mul, float84div
35 * Comparison operators:
36 * float48eq, float48ne, float48lt, float48le, float48gt, float48ge
37 * float84eq, float84ne, float84lt, float84le, float84gt, float84ge
39 * (You can do the arithmetic and comparison stuff using conversion
40 * routines, but then you pay the overhead of converting...)
42 * XXX GLUESOME STUFF. FIX IT! -AY '94
44 * Added some additional conversion routines and cleaned up
45 * a bit of the existing code. Need to change the error checking
46 * for calls to pow(), exp() since on some machines (my Linux box
47 * included) these routines do not set errno. - tgl 97/05/10
52 #include <float.h> /* faked on sunos4 */
60 #define MAXINT INT_MAX
68 #include "utils/builtins.h"
75 #define SHRT_MAX 32767
78 #define SHRT_MIN (-32768)
81 #define FORMAT 'g' /* use "g" output format as standard
83 /* not sure what the following should be, but better to make it over-sufficient */
84 #define MAXFLOATWIDTH 64
85 #define MAXDOUBLEWIDTH 128
87 #if !(NeXT && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_2)
88 /* NS3.3 has conflicting declarations of these in <math.h> */
91 extern double atof(const char *p);
97 static double cbrt(double x);
100 #if !defined(nextstep)
101 extern double cbrt(double x);
108 static double rint(double x);
111 extern double rint(double x);
117 /* ========== USER I/O ROUTINES ========== */
120 #define FLOAT4_MAX FLT_MAX
121 #define FLOAT4_MIN FLT_MIN
122 #define FLOAT8_MAX DBL_MAX
123 #define FLOAT8_MIN DBL_MIN
126 * if FLOAT8_MIN and FLOAT8_MAX are the limits of the range a
127 * double can store, then how are we ever going to wind up
128 * with something stored in a double that is outside those
129 * limits? (and similarly for FLOAT4_{MIN,MAX}/float.)
130 * doesn't make sense to me, and it causes a
131 * floating point exception on linuxalpha, so UNSAFE_FLOATS
133 * (maybe someone wanted to allow for values other than DBL_MIN/
134 * DBL_MAX for FLOAT8_MIN/FLOAT8_MAX?)
136 * according to Richard Henderson this is a known bug in gcc on
137 * the Alpha. might as well leave the workaround in
138 * until the distributions are updated.
141 #if ( defined(linux) && defined(__alpha__) ) && !defined(UNSAFE_FLOATS)
142 #define UNSAFE_FLOATS
146 check to see if a float4 val is outside of
147 the FLOAT4_MIN, FLOAT4_MAX bounds.
149 raise an elog warning if it is
152 CheckFloat4Val(double val)
156 * defining unsafe floats's will make float4 and float8 ops faster at
157 * the cost of safety, of course!
162 if (fabs(val) > FLOAT4_MAX)
163 elog(ERROR, "Bad float4 input format -- overflow");
164 if (val != 0.0 && fabs(val) < FLOAT4_MIN)
165 elog(ERROR, "Bad float4 input format -- underflow");
167 #endif /* UNSAFE_FLOATS */
171 check to see if a float8 val is outside of
172 the FLOAT8_MIN, FLOAT8_MAX bounds.
174 raise an elog warning if it is
177 CheckFloat8Val(double val)
181 * defining unsafe floats's will make float4 and float8 ops faster at
182 * the cost of safety, of course!
187 if (fabs(val) > FLOAT8_MAX)
188 elog(ERROR, "Bad float8 input format -- overflow");
189 if (val != 0.0 && fabs(val) < FLOAT8_MIN)
190 elog(ERROR, "Bad float8 input format -- underflow");
192 #endif /* UNSAFE_FLOATS */
196 * float4in - converts "num" to float
198 * {<sp>} [+|-] {digit} [.{digit}] [<exp>]
199 * where <sp> is a space, digit is 0-9,
200 * <exp> is "e" or "E" followed by an integer.
205 float32 result = (float32) palloc(sizeof(float32data));
210 val = strtod(num, &endptr);
213 /* Should we accept "NaN" or "Infinity" for float4? */
214 elog(ERROR, "Bad float4 input format '%s'", num);
219 elog(ERROR, "Input '%s' is out of range for float4", num);
223 * if we get here, we have a legal double, still need to check to see
224 * if it's a legal float
234 * float4out - converts a float4 number to a string
235 * using a standard output format
238 float4out(float32 num)
240 char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
243 return strcpy(ascii, "(null)");
245 sprintf(ascii, "%.*g", FLT_DIG, *num);
251 * float8in - converts "num" to float8
253 * {<sp>} [+|-] {digit} [.{digit}] [<exp>]
254 * where <sp> is a space, digit is 0-9,
255 * <exp> is "e" or "E" followed by an integer.
260 float64 result = (float64) palloc(sizeof(float64data));
265 val = strtod(num, &endptr);
268 if (strcasecmp(num, "NaN") == 0)
270 else if (strcasecmp(num, "Infinity") == 0)
273 elog(ERROR, "Bad float8 input format '%s'", num);
278 elog(ERROR, "Input '%s' is out of range for float8", num);
289 * float8out - converts float8 number to a string
290 * using a standard output format
293 float8out(float64 num)
295 char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
298 return strcpy(ascii, "(null)");
301 return strcpy(ascii, "NaN");
303 return strcpy(ascii, "Infinity");
305 sprintf(ascii, "%.*g", DBL_DIG, *num);
309 /* ========== PUBLIC ROUTINES ========== */
313 * ======================
314 * FLOAT4 BASE OPERATIONS
315 * ======================
319 * float4abs - returns a pointer to |arg1| (absolute value)
322 float4abs(float32 arg1)
328 return (float32) NULL;
334 result = (float32) palloc(sizeof(float32data));
340 * float4um - returns a pointer to -arg1 (unary minus)
343 float4um(float32 arg1)
349 return (float32) NULL;
351 val = ((*arg1 != 0) ? -(*arg1) : *arg1);
354 result = (float32) palloc(sizeof(float32data));
360 float4larger(float32 arg1, float32 arg2)
365 return (float32) NULL;
367 result = (float32) palloc(sizeof(float32data));
369 *result = ((*arg1 > *arg2) ? *arg1 : *arg2);
374 float4smaller(float32 arg1, float32 arg2)
379 return (float32) NULL;
381 result = (float32) palloc(sizeof(float32data));
383 *result = ((*arg1 > *arg2) ? *arg2 : *arg1);
388 * ======================
389 * FLOAT8 BASE OPERATIONS
390 * ======================
394 * float8abs - returns a pointer to |arg1| (absolute value)
397 float8abs(float64 arg1)
403 return (float64) NULL;
405 result = (float64) palloc(sizeof(float64data));
415 * float8um - returns a pointer to -arg1 (unary minus)
418 float8um(float64 arg1)
424 return (float64) NULL;
426 val = ((*arg1 != 0) ? -(*arg1) : *arg1);
429 result = (float64) palloc(sizeof(float64data));
435 float8larger(float64 arg1, float64 arg2)
440 return (float64) NULL;
442 result = (float64) palloc(sizeof(float64data));
444 *result = ((*arg1 > *arg2) ? *arg1 : *arg2);
449 float8smaller(float64 arg1, float64 arg2)
454 return (float64) NULL;
456 result = (float64) palloc(sizeof(float64data));
458 *result = ((*arg1 > *arg2) ? *arg2 : *arg1);
464 * ====================
465 * ARITHMETIC OPERATORS
466 * ====================
470 * float4pl - returns a pointer to arg1 + arg2
471 * float4mi - returns a pointer to arg1 - arg2
472 * float4mul - returns a pointer to arg1 * arg2
473 * float4div - returns a pointer to arg1 / arg2
474 * float4inc - returns a poniter to arg1 + 1.0
477 float4pl(float32 arg1, float32 arg2)
483 return (float32) NULL;
488 result = (float32) palloc(sizeof(float32data));
495 float4mi(float32 arg1, float32 arg2)
501 return (float32) NULL;
506 result = (float32) palloc(sizeof(float32data));
512 float4mul(float32 arg1, float32 arg2)
518 return (float32) NULL;
523 result = (float32) palloc(sizeof(float32data));
529 float4div(float32 arg1, float32 arg2)
535 return (float32) NULL;
538 elog(ERROR, "float4div: divide by zero error");
543 result = (float32) palloc(sizeof(float32data));
549 float4inc(float32 arg1)
555 return (float32) NULL;
557 val = *arg1 + (float32data) 1.0;
560 result = (float32) palloc(sizeof(float32data));
566 * float8pl - returns a pointer to arg1 + arg2
567 * float8mi - returns a pointer to arg1 - arg2
568 * float8mul - returns a pointer to arg1 * arg2
569 * float8div - returns a pointer to arg1 / arg2
570 * float8inc - returns a pointer to arg1 + 1.0
573 float8pl(float64 arg1, float64 arg2)
579 return (float64) NULL;
581 result = (float64) palloc(sizeof(float64data));
590 float8mi(float64 arg1, float64 arg2)
596 return (float64) NULL;
598 result = (float64) palloc(sizeof(float64data));
607 float8mul(float64 arg1, float64 arg2)
613 return (float64) NULL;
615 result = (float64) palloc(sizeof(float64data));
624 float8div(float64 arg1, float64 arg2)
630 return (float64) NULL;
632 result = (float64) palloc(sizeof(float64data));
635 elog(ERROR, "float8div: divide by zero error");
644 float8inc(float64 arg1)
650 return (float64) NULL;
652 val = *arg1 + (float64data) 1.0;
654 result = (float64) palloc(sizeof(float64data));
661 * ====================
662 * COMPARISON OPERATORS
663 * ====================
667 * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
670 float4eq(float32 arg1, float32 arg2)
675 return *arg1 == *arg2;
679 float4ne(float32 arg1, float32 arg2)
684 return *arg1 != *arg2;
688 float4lt(float32 arg1, float32 arg2)
693 return *arg1 < *arg2;
697 float4le(float32 arg1, float32 arg2)
702 return *arg1 <= *arg2;
706 float4gt(float32 arg1, float32 arg2)
711 return *arg1 > *arg2;
715 float4ge(float32 arg1, float32 arg2)
720 return *arg1 >= *arg2;
724 * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
727 float8eq(float64 arg1, float64 arg2)
732 return *arg1 == *arg2;
736 float8ne(float64 arg1, float64 arg2)
741 return *arg1 != *arg2;
745 float8lt(float64 arg1, float64 arg2)
750 return *arg1 < *arg2;
754 float8le(float64 arg1, float64 arg2)
759 return *arg1 <= *arg2;
763 float8gt(float64 arg1, float64 arg2)
768 return *arg1 > *arg2;
772 float8ge(float64 arg1, float64 arg2)
777 return *arg1 >= *arg2;
782 * ===================
783 * CONVERSION ROUTINES
784 * ===================
788 * ftod - converts a float4 number to a float8 number
796 return (float64) NULL;
798 result = (float64) palloc(sizeof(float64data));
806 * dtof - converts a float8 number to a float4 number
814 return (float32) NULL;
816 CheckFloat4Val(*num);
818 result = (float32) palloc(sizeof(float32data));
826 * dtoi4 - converts a float8 number to an int4 number
833 if (!PointerIsValid(num))
834 elog(ERROR, "dtoi4: unable to convert null");
836 if ((*num < INT_MIN) || (*num > INT_MAX))
837 elog(ERROR, "dtoi4: integer out of range");
845 * dtoi2 - converts a float8 number to an int2 number
852 if (!PointerIsValid(num))
853 elog(ERROR, "dtoi2: unable to convert null");
855 if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
856 elog(ERROR, "dtoi2: integer out of range");
864 * i4tod - converts an int4 number to a float8 number
871 result = (float64) palloc(sizeof(float64data));
879 * i2tod - converts an int2 number to a float8 number
886 result = (float64) palloc(sizeof(float64data));
894 * ftoi4 - converts a float8 number to an int4 number
901 if (!PointerIsValid(num))
902 elog(ERROR, "ftoi4: unable to convert null");
904 if ((*num < INT_MIN) || (*num > INT_MAX))
905 elog(ERROR, "ftoi4: integer out of range");
913 * ftoi2 - converts a float8 number to an int2 number
920 if (!PointerIsValid(num))
921 elog(ERROR, "ftoi2: unable to convert null");
923 if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
924 elog(ERROR, "ftoi2: integer out of range");
932 * i4tof - converts an int4 number to a float8 number
939 result = (float32) palloc(sizeof(float32data));
947 * i2tof - converts an int2 number to a float8 number
954 result = (float32) palloc(sizeof(float32data));
962 * float8_text - converts a float8 number to a text string
965 float8_text(float64 num)
971 str = float8out(num);
972 len = (strlen(str) + VARHDRSZ);
974 result = palloc(len);
976 VARSIZE(result) = len;
977 memmove(VARDATA(result), str, (len - VARHDRSZ));
981 } /* float8_text() */
985 * text_float8 - converts a text string to a float8 number
988 text_float8(text *string)
994 len = (VARSIZE(string) - VARHDRSZ);
995 str = palloc(len + 1);
996 memmove(str, VARDATA(string), len);
999 result = float8in(str);
1003 } /* text_float8() */
1007 * float4_text - converts a float4 number to a text string
1010 float4_text(float32 num)
1016 str = float4out(num);
1017 len = (strlen(str) + VARHDRSZ);
1019 result = palloc(len);
1021 VARSIZE(result) = len;
1022 memmove(VARDATA(result), str, (len - VARHDRSZ));
1026 } /* float4_text() */
1030 * text_float4 - converts a text string to a float4 number
1033 text_float4(text *string)
1039 len = (VARSIZE(string) - VARHDRSZ);
1040 str = palloc(len + 1);
1041 memmove(str, VARDATA(string), len);
1042 *(str + len) = '\0';
1044 result = float4in(str);
1048 } /* text_float4() */
1052 * =======================
1053 * RANDOM FLOAT8 OPERATORS
1054 * =======================
1058 * dround - returns a pointer to ROUND(arg1)
1061 dround(float64 arg1)
1067 return (float64) NULL;
1069 result = (float64) palloc(sizeof(float64data));
1072 *result = (float64data) rint(tmp);
1078 * dtrunc - returns a pointer to truncation of arg1,
1079 * arg1 >= 0 ... the greatest integer as float8 less
1080 * than or equal to arg1
1081 * arg1 < 0 ... the greatest integer as float8 greater
1082 * than or equal to arg1
1085 dtrunc(float64 arg1)
1091 return (float64) NULL;
1093 result = (float64) palloc(sizeof(float64data));
1097 *result = (float64data) floor(tmp);
1099 *result = (float64data) -(floor(-tmp));
1105 * dsqrt - returns a pointer to square root of arg1
1114 return (float64) NULL;
1116 result = (float64) palloc(sizeof(float64data));
1119 *result = (float64data) sqrt(tmp);
1125 * dcbrt - returns a pointer to cube root of arg1
1134 return (float64) NULL;
1136 result = (float64) palloc(sizeof(float64data));
1139 *result = (float64data) cbrt(tmp);
1145 * dpow - returns a pointer to pow(arg1,arg2)
1148 dpow(float64 arg1, float64 arg2)
1155 return (float64) NULL;
1157 result = (float64) palloc(sizeof(float64data));
1162 /* We must check both for errno getting set and for a NaN result,
1163 * in order to deal with the vagaries of different platforms...
1166 *result = (float64data) pow(tmp1, tmp2);
1172 elog(ERROR, "pow() result is out of range");
1174 CheckFloat8Val(*result);
1180 * dexp - returns a pointer to the exponential function of arg1
1189 return (float64) NULL;
1191 result = (float64) palloc(sizeof(float64data));
1195 /* We must check both for errno getting set and for a NaN result,
1196 * in order to deal with the vagaries of different platforms.
1197 * Also, a zero result implies unreported underflow.
1200 *result = (float64data) exp(tmp);
1201 if (errno != 0 || *result == 0.0
1206 elog(ERROR, "exp() result is out of range");
1208 CheckFloat8Val(*result);
1214 * dlog1 - returns a pointer to the natural logarithm of arg1
1215 * ("dlog" is already a logging routine...)
1224 return (float64) NULL;
1226 result = (float64) palloc(sizeof(float64data));
1230 elog(ERROR, "can't take log of zero");
1232 elog(ERROR, "can't take log of a negative number");
1233 *result = (float64data) log(tmp);
1235 CheckFloat8Val(*result);
1241 * ====================
1242 * ARITHMETIC OPERATORS
1243 * ====================
1247 * float48pl - returns a pointer to arg1 + arg2
1248 * float48mi - returns a pointer to arg1 - arg2
1249 * float48mul - returns a pointer to arg1 * arg2
1250 * float48div - returns a pointer to arg1 / arg2
1253 float48pl(float32 arg1, float64 arg2)
1258 return (float64) NULL;
1260 result = (float64) palloc(sizeof(float64data));
1262 *result = *arg1 + *arg2;
1263 CheckFloat8Val(*result);
1268 float48mi(float32 arg1, float64 arg2)
1273 return (float64) NULL;
1275 result = (float64) palloc(sizeof(float64data));
1277 *result = *arg1 - *arg2;
1278 CheckFloat8Val(*result);
1283 float48mul(float32 arg1, float64 arg2)
1288 return (float64) NULL;
1290 result = (float64) palloc(sizeof(float64data));
1292 *result = *arg1 * *arg2;
1293 CheckFloat8Val(*result);
1298 float48div(float32 arg1, float64 arg2)
1303 return (float64) NULL;
1305 result = (float64) palloc(sizeof(float64data));
1308 elog(ERROR, "float48div: divide by zero");
1310 *result = *arg1 / *arg2;
1311 CheckFloat8Val(*result);
1316 * float84pl - returns a pointer to arg1 + arg2
1317 * float84mi - returns a pointer to arg1 - arg2
1318 * float84mul - returns a pointer to arg1 * arg2
1319 * float84div - returns a pointer to arg1 / arg2
1322 float84pl(float64 arg1, float32 arg2)
1327 return (float64) NULL;
1329 result = (float64) palloc(sizeof(float64data));
1331 *result = *arg1 + *arg2;
1332 CheckFloat8Val(*result);
1337 float84mi(float64 arg1, float32 arg2)
1342 return (float64) NULL;
1344 result = (float64) palloc(sizeof(float64data));
1346 *result = *arg1 - *arg2;
1347 CheckFloat8Val(*result);
1352 float84mul(float64 arg1, float32 arg2)
1358 return (float64) NULL;
1360 result = (float64) palloc(sizeof(float64data));
1362 *result = *arg1 * *arg2;
1363 CheckFloat8Val(*result);
1368 float84div(float64 arg1, float32 arg2)
1373 return (float64) NULL;
1375 result = (float64) palloc(sizeof(float64data));
1378 elog(ERROR, "float48div: divide by zero");
1380 *result = *arg1 / *arg2;
1381 CheckFloat8Val(*result);
1386 * ====================
1387 * COMPARISON OPERATORS
1388 * ====================
1392 * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
1395 float48eq(float32 arg1, float64 arg2)
1400 return *arg1 == *arg2;
1404 float48ne(float32 arg1, float64 arg2)
1409 return *arg1 != *arg2;
1413 float48lt(float32 arg1, float64 arg2)
1418 return *arg1 < *arg2;
1422 float48le(float32 arg1, float64 arg2)
1427 return *arg1 <= *arg2;
1431 float48gt(float32 arg1, float64 arg2)
1436 return *arg1 > *arg2;
1440 float48ge(float32 arg1, float64 arg2)
1445 return *arg1 >= *arg2;
1449 * float84{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
1452 float84eq(float64 arg1, float32 arg2)
1457 return *arg1 == *arg2;
1461 float84ne(float64 arg1, float32 arg2)
1466 return *arg1 != *arg2;
1470 float84lt(float64 arg1, float32 arg2)
1475 return *arg1 < *arg2;
1479 float84le(float64 arg1, float32 arg2)
1484 return *arg1 <= *arg2;
1488 float84gt(float64 arg1, float32 arg2)
1493 return *arg1 > *arg2;
1497 float84ge(float64 arg1, float32 arg2)
1502 return *arg1 >= *arg2;
1505 /* ========== PRIVATE ROUTINES ========== */
1507 /* From "fdlibm" @ netlib.att.com */
1511 /* @(#)s_rint.c 5.1 93/09/24 */
1513 * ====================================================
1514 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
1516 * Developed at SunPro, a Sun Microsystems, Inc. business.
1517 * Permission to use, copy, modify, and distribute this
1518 * software is freely granted, provided that this notice
1520 * ====================================================
1525 * Return x rounded to integral value according to the prevailing
1528 * Using floating addition.
1530 * Inexact flag raised if x not equal to rint(x).
1540 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
1541 -4.50359962737049600000e+15,/* 0xC3300000, 0x00000000 */
1563 n0 = (*((int *) &one) >> 29) ^ 1;
1564 i0 = *(n0 + (int *) &x);
1565 sx = (i0 >> 31) & 1;
1566 i1 = *(1 - n0 + (int *) &x);
1567 j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
1572 if (((i0 & 0x7fffffff) | i1) == 0)
1574 i1 |= (i0 & 0x0fffff);
1576 i0 |= ((i1 | -i1) >> 12) & 0x80000;
1577 *(n0 + (int *) &x) = i0;
1580 i0 = *(n0 + (int *) &t);
1581 *(n0 + (int *) &t) = (i0 & 0x7fffffff) | (sx << 31);
1586 i = (0x000fffff) >> j0;
1587 if (((i0 & i) | i1) == 0)
1588 return x; /* x is integral */
1590 if (((i0 & i) | i1) != 0)
1595 i0 = (i0 & (~i)) | ((0x20000) >> j0);
1602 return x + x; /* inf or NaN */
1604 return x; /* x is integral */
1608 i = ((unsigned) (0xffffffff)) >> (j0 - 20);
1610 return x; /* x is integral */
1613 i1 = (i1 & (~i)) | ((0x40000000) >> (j0 - 20));
1615 *(n0 + (int *) &x) = i0;
1616 *(1 - n0 + (int *) &x) = i1;
1618 return w - TWO52[sx];
1621 #endif /* !HAVE_RINT */
1630 int isneg = (x < 0.0);
1631 double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
1633 return isneg ? -tmpres : tmpres;
1636 #endif /* !HAVE_CBRT */