1 /*-------------------------------------------------------------------------
4 * Functions for the built-in floating-point types.
6 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.93 2003/08/04 02:40:04 momjian Exp $
13 *-------------------------------------------------------------------------
18 * float4in, float4out, float4recv, float4send
19 * float4abs, float4um, float4up
21 * float8in, float8out, float8recv, float8send
22 * float8abs, float8um, float8up
23 * Arithmetic operators:
24 * float4pl, float4mi, float4mul, float4div
25 * float8pl, float8mi, float8mul, float8div
26 * Comparison operators:
27 * float4eq, float4ne, float4lt, float4le, float4gt, float4ge, float4cmp
28 * float8eq, float8ne, float8lt, float8le, float8gt, float8ge, float8cmp
29 * Conversion routines:
30 * ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
33 * dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
34 * Arithmetic operators:
35 * float48pl, float48mi, float48mul, float48div
36 * float84pl, float84mi, float84mul, float84div
37 * Comparison operators:
38 * float48eq, float48ne, float48lt, float48le, float48gt, float48ge
39 * float84eq, float84ne, float84lt, float84le, float84gt, float84ge
41 * (You can do the arithmetic and comparison stuff using conversion
42 * routines, but then you pay the overhead of invoking a separate
43 * conversion function...)
45 * XXX GLUESOME STUFF. FIX IT! -AY '94
47 * Added some additional conversion routines and cleaned up
48 * a bit of the existing code. Need to change the error checking
49 * for calls to pow(), exp() since on some machines (my Linux box
50 * included) these routines do not set errno. - tgl 97/05/10
57 #include <float.h> /* faked on sunos4 */
61 /* for finite() on Solaris */
66 #include "catalog/pg_type.h"
68 #include "libpq/pqformat.h"
69 #include "utils/array.h"
70 #include "utils/builtins.h"
74 static double cbrt(double x);
75 #endif /* HAVE_CBRT */
78 /* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
79 #define M_PI 3.14159265358979323846
87 #define SHRT_MAX 32767
90 #define SHRT_MIN (-32768)
93 /* not sure what the following should be, but better to make it over-sufficient */
94 #define MAXFLOATWIDTH 64
95 #define MAXDOUBLEWIDTH 128
97 /* ========== USER I/O ROUTINES ========== */
100 #define FLOAT4_MAX FLT_MAX
101 #define FLOAT4_MIN FLT_MIN
102 #define FLOAT8_MAX DBL_MAX
103 #define FLOAT8_MIN DBL_MIN
106 /* Configurable GUC parameter */
107 int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
110 static void CheckFloat4Val(double val);
111 static void CheckFloat8Val(double val);
112 static int float4_cmp_internal(float4 a, float4 b);
113 static int float8_cmp_internal(float8 a, float8 b);
117 * check to see if a float4 val is outside of
118 * the FLOAT4_MIN, FLOAT4_MAX bounds.
120 * raise an ereport warning if it is
123 CheckFloat4Val(double val)
126 * defining unsafe floats's will make float4 and float8 ops faster at
127 * the cost of safety, of course!
132 if (fabs(val) > FLOAT4_MAX)
134 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
135 errmsg("float4 value out of range: overflow")));
136 if (val != 0.0 && fabs(val) < FLOAT4_MIN)
138 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
139 errmsg("float4 value out of range: underflow")));
142 #endif /* UNSAFE_FLOATS */
146 * check to see if a float8 val is outside of
147 * the FLOAT8_MIN, FLOAT8_MAX bounds.
149 * raise an ereport error if it is
152 CheckFloat8Val(double val)
155 * defining unsafe floats's will make float4 and float8 ops faster at
156 * the cost of safety, of course!
161 if (fabs(val) > FLOAT8_MAX)
163 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
164 errmsg("float8 value out of range: overflow")));
165 if (val != 0.0 && fabs(val) < FLOAT8_MIN)
167 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
168 errmsg("float8 value out of range: underflow")));
169 #endif /* UNSAFE_FLOATS */
173 * float4in - converts "num" to float
175 * {<sp>} [+|-] {digit} [.{digit}] [<exp>]
176 * where <sp> is a space, digit is 0-9,
177 * <exp> is "e" or "E" followed by an integer.
180 float4in(PG_FUNCTION_ARGS)
182 char *num = PG_GETARG_CSTRING(0);
187 val = strtod(num, &endptr);
191 * XXX we should accept "Infinity" and "-Infinity" too, but what
192 * are the correct values to assign? HUGE_VAL will provoke an
193 * error from CheckFloat4Val.
195 if (strcasecmp(num, "NaN") == 0)
199 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
200 errmsg("invalid input syntax for float4: \"%s\"",
207 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
208 errmsg("\"%s\" is out of range for float4", num)));
212 * if we get here, we have a legal double, still need to check to see
213 * if it's a legal float
217 PG_RETURN_FLOAT4((float4) val);
221 * float4out - converts a float4 number to a string
222 * using a standard output format
225 float4out(PG_FUNCTION_ARGS)
227 float4 num = PG_GETARG_FLOAT4(0);
228 char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
233 PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
234 infflag = isinf(num);
236 PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));
238 PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));
240 ndig = FLT_DIG + extra_float_digits;
244 sprintf(ascii, "%.*g", ndig, num);
246 PG_RETURN_CSTRING(ascii);
250 * float4recv - converts external binary format to float4
253 float4recv(PG_FUNCTION_ARGS)
255 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
257 PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));
261 * float4send - converts float4 to binary format
264 float4send(PG_FUNCTION_ARGS)
266 float4 num = PG_GETARG_FLOAT4(0);
269 pq_begintypsend(&buf);
270 pq_sendfloat4(&buf, num);
271 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
275 * float8in - converts "num" to float8
277 * {<sp>} [+|-] {digit} [.{digit}] [<exp>]
278 * where <sp> is a space, digit is 0-9,
279 * <exp> is "e" or "E" followed by an integer.
282 float8in(PG_FUNCTION_ARGS)
284 char *num = PG_GETARG_CSTRING(0);
289 val = strtod(num, &endptr);
292 if (strcasecmp(num, "NaN") == 0)
294 else if (strcasecmp(num, "Infinity") == 0)
296 else if (strcasecmp(num, "-Infinity") == 0)
300 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
301 errmsg("invalid input syntax for float8: \"%s\"",
308 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
309 errmsg("\"%s\" is out of range for float8", num)));
314 PG_RETURN_FLOAT8(val);
318 * float8out - converts float8 number to a string
319 * using a standard output format
322 float8out(PG_FUNCTION_ARGS)
324 float8 num = PG_GETARG_FLOAT8(0);
325 char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
330 PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
331 infflag = isinf(num);
333 PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));
335 PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));
337 ndig = DBL_DIG + extra_float_digits;
341 sprintf(ascii, "%.*g", ndig, num);
343 PG_RETURN_CSTRING(ascii);
347 * float8recv - converts external binary format to float8
350 float8recv(PG_FUNCTION_ARGS)
352 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
354 PG_RETURN_FLOAT8(pq_getmsgfloat8(buf));
358 * float8send - converts float8 to binary format
361 float8send(PG_FUNCTION_ARGS)
363 float8 num = PG_GETARG_FLOAT8(0);
366 pq_begintypsend(&buf);
367 pq_sendfloat8(&buf, num);
368 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
372 /* ========== PUBLIC ROUTINES ========== */
376 * ======================
377 * FLOAT4 BASE OPERATIONS
378 * ======================
382 * float4abs - returns |arg1| (absolute value)
385 float4abs(PG_FUNCTION_ARGS)
387 float4 arg1 = PG_GETARG_FLOAT4(0);
389 PG_RETURN_FLOAT4((float4) fabs(arg1));
393 * float4um - returns -arg1 (unary minus)
396 float4um(PG_FUNCTION_ARGS)
398 float4 arg1 = PG_GETARG_FLOAT4(0);
400 PG_RETURN_FLOAT4((float4) -arg1);
404 float4up(PG_FUNCTION_ARGS)
406 float4 arg = PG_GETARG_FLOAT4(0);
408 PG_RETURN_FLOAT4(arg);
412 float4larger(PG_FUNCTION_ARGS)
414 float4 arg1 = PG_GETARG_FLOAT4(0);
415 float4 arg2 = PG_GETARG_FLOAT4(1);
418 if (float4_cmp_internal(arg1, arg2) > 0)
422 PG_RETURN_FLOAT4(result);
426 float4smaller(PG_FUNCTION_ARGS)
428 float4 arg1 = PG_GETARG_FLOAT4(0);
429 float4 arg2 = PG_GETARG_FLOAT4(1);
432 if (float4_cmp_internal(arg1, arg2) < 0)
436 PG_RETURN_FLOAT4(result);
440 * ======================
441 * FLOAT8 BASE OPERATIONS
442 * ======================
446 * float8abs - returns |arg1| (absolute value)
449 float8abs(PG_FUNCTION_ARGS)
451 float8 arg1 = PG_GETARG_FLOAT8(0);
456 CheckFloat8Val(result);
457 PG_RETURN_FLOAT8(result);
462 * float8um - returns -arg1 (unary minus)
465 float8um(PG_FUNCTION_ARGS)
467 float8 arg1 = PG_GETARG_FLOAT8(0);
470 result = ((arg1 != 0) ? -(arg1) : arg1);
472 CheckFloat8Val(result);
473 PG_RETURN_FLOAT8(result);
477 float8up(PG_FUNCTION_ARGS)
479 float8 arg = PG_GETARG_FLOAT8(0);
481 PG_RETURN_FLOAT8(arg);
485 float8larger(PG_FUNCTION_ARGS)
487 float8 arg1 = PG_GETARG_FLOAT8(0);
488 float8 arg2 = PG_GETARG_FLOAT8(1);
491 if (float8_cmp_internal(arg1, arg2) > 0)
495 PG_RETURN_FLOAT8(result);
499 float8smaller(PG_FUNCTION_ARGS)
501 float8 arg1 = PG_GETARG_FLOAT8(0);
502 float8 arg2 = PG_GETARG_FLOAT8(1);
505 if (float8_cmp_internal(arg1, arg2) < 0)
509 PG_RETURN_FLOAT8(result);
514 * ====================
515 * ARITHMETIC OPERATORS
516 * ====================
520 * float4pl - returns arg1 + arg2
521 * float4mi - returns arg1 - arg2
522 * float4mul - returns arg1 * arg2
523 * float4div - returns arg1 / arg2
526 float4pl(PG_FUNCTION_ARGS)
528 float4 arg1 = PG_GETARG_FLOAT4(0);
529 float4 arg2 = PG_GETARG_FLOAT4(1);
532 result = arg1 + arg2;
533 CheckFloat4Val(result);
534 PG_RETURN_FLOAT4((float4) result);
538 float4mi(PG_FUNCTION_ARGS)
540 float4 arg1 = PG_GETARG_FLOAT4(0);
541 float4 arg2 = PG_GETARG_FLOAT4(1);
544 result = arg1 - arg2;
545 CheckFloat4Val(result);
546 PG_RETURN_FLOAT4((float4) result);
550 float4mul(PG_FUNCTION_ARGS)
552 float4 arg1 = PG_GETARG_FLOAT4(0);
553 float4 arg2 = PG_GETARG_FLOAT4(1);
556 result = arg1 * arg2;
557 CheckFloat4Val(result);
558 PG_RETURN_FLOAT4((float4) result);
562 float4div(PG_FUNCTION_ARGS)
564 float4 arg1 = PG_GETARG_FLOAT4(0);
565 float4 arg2 = PG_GETARG_FLOAT4(1);
570 (errcode(ERRCODE_DIVISION_BY_ZERO),
571 errmsg("division by zero")));
573 /* Do division in float8, then check for overflow */
574 result = (float8) arg1 / (float8) arg2;
576 CheckFloat4Val(result);
577 PG_RETURN_FLOAT4((float4) result);
581 * float8pl - returns arg1 + arg2
582 * float8mi - returns arg1 - arg2
583 * float8mul - returns arg1 * arg2
584 * float8div - returns arg1 / arg2
587 float8pl(PG_FUNCTION_ARGS)
589 float8 arg1 = PG_GETARG_FLOAT8(0);
590 float8 arg2 = PG_GETARG_FLOAT8(1);
593 result = arg1 + arg2;
595 CheckFloat8Val(result);
596 PG_RETURN_FLOAT8(result);
600 float8mi(PG_FUNCTION_ARGS)
602 float8 arg1 = PG_GETARG_FLOAT8(0);
603 float8 arg2 = PG_GETARG_FLOAT8(1);
606 result = arg1 - arg2;
608 CheckFloat8Val(result);
609 PG_RETURN_FLOAT8(result);
613 float8mul(PG_FUNCTION_ARGS)
615 float8 arg1 = PG_GETARG_FLOAT8(0);
616 float8 arg2 = PG_GETARG_FLOAT8(1);
619 result = arg1 * arg2;
621 CheckFloat8Val(result);
622 PG_RETURN_FLOAT8(result);
626 float8div(PG_FUNCTION_ARGS)
628 float8 arg1 = PG_GETARG_FLOAT8(0);
629 float8 arg2 = PG_GETARG_FLOAT8(1);
634 (errcode(ERRCODE_DIVISION_BY_ZERO),
635 errmsg("division by zero")));
637 result = arg1 / arg2;
639 CheckFloat8Val(result);
640 PG_RETURN_FLOAT8(result);
645 * ====================
646 * COMPARISON OPERATORS
647 * ====================
651 * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
654 float4_cmp_internal(float4 a, float4 b)
657 * We consider all NANs to be equal and larger than any non-NAN. This
658 * is somewhat arbitrary; the important thing is to have a consistent
664 return 0; /* NAN = NAN */
666 return 1; /* NAN > non-NAN */
670 return -1; /* non-NAN < NAN */
684 float4eq(PG_FUNCTION_ARGS)
686 float4 arg1 = PG_GETARG_FLOAT4(0);
687 float4 arg2 = PG_GETARG_FLOAT4(1);
689 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);
693 float4ne(PG_FUNCTION_ARGS)
695 float4 arg1 = PG_GETARG_FLOAT4(0);
696 float4 arg2 = PG_GETARG_FLOAT4(1);
698 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);
702 float4lt(PG_FUNCTION_ARGS)
704 float4 arg1 = PG_GETARG_FLOAT4(0);
705 float4 arg2 = PG_GETARG_FLOAT4(1);
707 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);
711 float4le(PG_FUNCTION_ARGS)
713 float4 arg1 = PG_GETARG_FLOAT4(0);
714 float4 arg2 = PG_GETARG_FLOAT4(1);
716 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);
720 float4gt(PG_FUNCTION_ARGS)
722 float4 arg1 = PG_GETARG_FLOAT4(0);
723 float4 arg2 = PG_GETARG_FLOAT4(1);
725 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);
729 float4ge(PG_FUNCTION_ARGS)
731 float4 arg1 = PG_GETARG_FLOAT4(0);
732 float4 arg2 = PG_GETARG_FLOAT4(1);
734 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);
738 btfloat4cmp(PG_FUNCTION_ARGS)
740 float4 arg1 = PG_GETARG_FLOAT4(0);
741 float4 arg2 = PG_GETARG_FLOAT4(1);
743 PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
747 * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
750 float8_cmp_internal(float8 a, float8 b)
753 * We consider all NANs to be equal and larger than any non-NAN. This
754 * is somewhat arbitrary; the important thing is to have a consistent
760 return 0; /* NAN = NAN */
762 return 1; /* NAN > non-NAN */
766 return -1; /* non-NAN < NAN */
780 float8eq(PG_FUNCTION_ARGS)
782 float8 arg1 = PG_GETARG_FLOAT8(0);
783 float8 arg2 = PG_GETARG_FLOAT8(1);
785 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
789 float8ne(PG_FUNCTION_ARGS)
791 float8 arg1 = PG_GETARG_FLOAT8(0);
792 float8 arg2 = PG_GETARG_FLOAT8(1);
794 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
798 float8lt(PG_FUNCTION_ARGS)
800 float8 arg1 = PG_GETARG_FLOAT8(0);
801 float8 arg2 = PG_GETARG_FLOAT8(1);
803 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
807 float8le(PG_FUNCTION_ARGS)
809 float8 arg1 = PG_GETARG_FLOAT8(0);
810 float8 arg2 = PG_GETARG_FLOAT8(1);
812 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
816 float8gt(PG_FUNCTION_ARGS)
818 float8 arg1 = PG_GETARG_FLOAT8(0);
819 float8 arg2 = PG_GETARG_FLOAT8(1);
821 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
825 float8ge(PG_FUNCTION_ARGS)
827 float8 arg1 = PG_GETARG_FLOAT8(0);
828 float8 arg2 = PG_GETARG_FLOAT8(1);
830 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
834 btfloat8cmp(PG_FUNCTION_ARGS)
836 float8 arg1 = PG_GETARG_FLOAT8(0);
837 float8 arg2 = PG_GETARG_FLOAT8(1);
839 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
844 * ===================
845 * CONVERSION ROUTINES
846 * ===================
850 * ftod - converts a float4 number to a float8 number
853 ftod(PG_FUNCTION_ARGS)
855 float4 num = PG_GETARG_FLOAT4(0);
857 PG_RETURN_FLOAT8((float8) num);
862 * dtof - converts a float8 number to a float4 number
865 dtof(PG_FUNCTION_ARGS)
867 float8 num = PG_GETARG_FLOAT8(0);
871 PG_RETURN_FLOAT4((float4) num);
876 * dtoi4 - converts a float8 number to an int4 number
879 dtoi4(PG_FUNCTION_ARGS)
881 float8 num = PG_GETARG_FLOAT8(0);
884 if ((num < INT_MIN) || (num > INT_MAX))
886 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
887 errmsg("integer out of range")));
889 result = (int32) rint(num);
890 PG_RETURN_INT32(result);
895 * dtoi2 - converts a float8 number to an int2 number
898 dtoi2(PG_FUNCTION_ARGS)
900 float8 num = PG_GETARG_FLOAT8(0);
903 if ((num < SHRT_MIN) || (num > SHRT_MAX))
905 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
906 errmsg("integer out of range")));
908 result = (int16) rint(num);
909 PG_RETURN_INT16(result);
914 * i4tod - converts an int4 number to a float8 number
917 i4tod(PG_FUNCTION_ARGS)
919 int32 num = PG_GETARG_INT32(0);
923 PG_RETURN_FLOAT8(result);
928 * i2tod - converts an int2 number to a float8 number
931 i2tod(PG_FUNCTION_ARGS)
933 int16 num = PG_GETARG_INT16(0);
937 PG_RETURN_FLOAT8(result);
942 * ftoi4 - converts a float4 number to an int4 number
945 ftoi4(PG_FUNCTION_ARGS)
947 float4 num = PG_GETARG_FLOAT4(0);
950 if ((num < INT_MIN) || (num > INT_MAX))
952 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
953 errmsg("integer out of range")));
955 result = (int32) rint(num);
956 PG_RETURN_INT32(result);
961 * ftoi2 - converts a float4 number to an int2 number
964 ftoi2(PG_FUNCTION_ARGS)
966 float4 num = PG_GETARG_FLOAT4(0);
969 if ((num < SHRT_MIN) || (num > SHRT_MAX))
971 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
972 errmsg("integer out of range")));
974 result = (int16) rint(num);
975 PG_RETURN_INT16(result);
980 * i4tof - converts an int4 number to a float8 number
983 i4tof(PG_FUNCTION_ARGS)
985 int32 num = PG_GETARG_INT32(0);
989 PG_RETURN_FLOAT4(result);
994 * i2tof - converts an int2 number to a float4 number
997 i2tof(PG_FUNCTION_ARGS)
999 int16 num = PG_GETARG_INT16(0);
1003 PG_RETURN_FLOAT4(result);
1008 * float8_text - converts a float8 number to a text string
1011 float8_text(PG_FUNCTION_ARGS)
1013 float8 num = PG_GETARG_FLOAT8(0);
1018 str = DatumGetCString(DirectFunctionCall1(float8out,
1019 Float8GetDatum(num)));
1021 len = strlen(str) + VARHDRSZ;
1023 result = (text *) palloc(len);
1025 VARATT_SIZEP(result) = len;
1026 memcpy(VARDATA(result), str, (len - VARHDRSZ));
1030 PG_RETURN_TEXT_P(result);
1035 * text_float8 - converts a text string to a float8 number
1038 text_float8(PG_FUNCTION_ARGS)
1040 text *string = PG_GETARG_TEXT_P(0);
1045 len = (VARSIZE(string) - VARHDRSZ);
1046 str = palloc(len + 1);
1047 memcpy(str, VARDATA(string), len);
1048 *(str + len) = '\0';
1050 result = DirectFunctionCall1(float8in, CStringGetDatum(str));
1054 PG_RETURN_DATUM(result);
1059 * float4_text - converts a float4 number to a text string
1062 float4_text(PG_FUNCTION_ARGS)
1064 float4 num = PG_GETARG_FLOAT4(0);
1069 str = DatumGetCString(DirectFunctionCall1(float4out,
1070 Float4GetDatum(num)));
1072 len = strlen(str) + VARHDRSZ;
1074 result = (text *) palloc(len);
1076 VARATT_SIZEP(result) = len;
1077 memcpy(VARDATA(result), str, (len - VARHDRSZ));
1081 PG_RETURN_TEXT_P(result);
1086 * text_float4 - converts a text string to a float4 number
1089 text_float4(PG_FUNCTION_ARGS)
1091 text *string = PG_GETARG_TEXT_P(0);
1096 len = (VARSIZE(string) - VARHDRSZ);
1097 str = palloc(len + 1);
1098 memcpy(str, VARDATA(string), len);
1099 *(str + len) = '\0';
1101 result = DirectFunctionCall1(float4in, CStringGetDatum(str));
1105 PG_RETURN_DATUM(result);
1110 * =======================
1111 * RANDOM FLOAT8 OPERATORS
1112 * =======================
1116 * dround - returns ROUND(arg1)
1119 dround(PG_FUNCTION_ARGS)
1121 float8 arg1 = PG_GETARG_FLOAT8(0);
1124 result = rint(arg1);
1126 PG_RETURN_FLOAT8(result);
1130 * dceil - returns the smallest integer greater than or
1131 * equal to the specified float
1134 dceil(PG_FUNCTION_ARGS)
1136 float8 arg1 = PG_GETARG_FLOAT8(0);
1138 PG_RETURN_FLOAT8(ceil(arg1));
1142 * dfloor - returns the largest integer lesser than or
1143 * equal to the specified float
1146 dfloor(PG_FUNCTION_ARGS)
1148 float8 arg1 = PG_GETARG_FLOAT8(0);
1150 PG_RETURN_FLOAT8(floor(arg1));
1154 * dsign - returns -1 if the argument is less than 0, 0
1155 * if the argument is equal to 0, and 1 if the
1156 * argument is greater than zero.
1159 dsign(PG_FUNCTION_ARGS)
1161 float8 arg1 = PG_GETARG_FLOAT8(0);
1171 PG_RETURN_FLOAT8(result);
1175 * dtrunc - returns truncation-towards-zero of arg1,
1176 * arg1 >= 0 ... the greatest integer less
1177 * than or equal to arg1
1178 * arg1 < 0 ... the least integer greater
1179 * than or equal to arg1
1182 dtrunc(PG_FUNCTION_ARGS)
1184 float8 arg1 = PG_GETARG_FLOAT8(0);
1188 result = floor(arg1);
1190 result = -floor(-arg1);
1192 PG_RETURN_FLOAT8(result);
1197 * dsqrt - returns square root of arg1
1200 dsqrt(PG_FUNCTION_ARGS)
1202 float8 arg1 = PG_GETARG_FLOAT8(0);
1207 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
1208 errmsg("cannot take square root of a negative number")));
1210 result = sqrt(arg1);
1212 CheckFloat8Val(result);
1213 PG_RETURN_FLOAT8(result);
1218 * dcbrt - returns cube root of arg1
1221 dcbrt(PG_FUNCTION_ARGS)
1223 float8 arg1 = PG_GETARG_FLOAT8(0);
1226 result = cbrt(arg1);
1227 PG_RETURN_FLOAT8(result);
1232 * dpow - returns pow(arg1,arg2)
1235 dpow(PG_FUNCTION_ARGS)
1237 float8 arg1 = PG_GETARG_FLOAT8(0);
1238 float8 arg2 = PG_GETARG_FLOAT8(1);
1242 * We must check both for errno getting set and for a NaN result, in
1243 * order to deal with the vagaries of different platforms...
1246 result = pow(arg1, arg2);
1253 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1254 errmsg("result is out of range")));
1256 CheckFloat8Val(result);
1257 PG_RETURN_FLOAT8(result);
1262 * dexp - returns the exponential function of arg1
1265 dexp(PG_FUNCTION_ARGS)
1267 float8 arg1 = PG_GETARG_FLOAT8(0);
1271 * We must check both for errno getting set and for a NaN result, in
1272 * order to deal with the vagaries of different platforms. Also, a
1273 * zero result implies unreported underflow.
1277 if (errno != 0 || result == 0.0
1283 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1284 errmsg("result is out of range")));
1286 CheckFloat8Val(result);
1287 PG_RETURN_FLOAT8(result);
1292 * dlog1 - returns the natural logarithm of arg1
1293 * ("dlog" is already a logging routine...)
1296 dlog1(PG_FUNCTION_ARGS)
1298 float8 arg1 = PG_GETARG_FLOAT8(0);
1303 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
1304 errmsg("cannot take log of zero")));
1308 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
1309 errmsg("cannot take log of a negative number")));
1313 CheckFloat8Val(result);
1314 PG_RETURN_FLOAT8(result);
1319 * dlog10 - returns the base 10 logarithm of arg1
1322 dlog10(PG_FUNCTION_ARGS)
1324 float8 arg1 = PG_GETARG_FLOAT8(0);
1329 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
1330 errmsg("cannot take log of zero")));
1334 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
1335 errmsg("cannot take log of a negative number")));
1337 result = log10(arg1);
1339 CheckFloat8Val(result);
1340 PG_RETURN_FLOAT8(result);
1345 * dacos - returns the arccos of arg1 (radians)
1348 dacos(PG_FUNCTION_ARGS)
1350 float8 arg1 = PG_GETARG_FLOAT8(0);
1354 result = acos(arg1);
1361 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1362 errmsg("input is out of range")));
1364 CheckFloat8Val(result);
1365 PG_RETURN_FLOAT8(result);
1370 * dasin - returns the arcsin of arg1 (radians)
1373 dasin(PG_FUNCTION_ARGS)
1375 float8 arg1 = PG_GETARG_FLOAT8(0);
1379 result = asin(arg1);
1386 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1387 errmsg("input is out of range")));
1389 CheckFloat8Val(result);
1390 PG_RETURN_FLOAT8(result);
1395 * datan - returns the arctan of arg1 (radians)
1398 datan(PG_FUNCTION_ARGS)
1400 float8 arg1 = PG_GETARG_FLOAT8(0);
1404 result = atan(arg1);
1411 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1412 errmsg("input is out of range")));
1414 CheckFloat8Val(result);
1415 PG_RETURN_FLOAT8(result);
1420 * atan2 - returns the arctan2 of arg1 (radians)
1423 datan2(PG_FUNCTION_ARGS)
1425 float8 arg1 = PG_GETARG_FLOAT8(0);
1426 float8 arg2 = PG_GETARG_FLOAT8(1);
1430 result = atan2(arg1, arg2);
1437 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1438 errmsg("input is out of range")));
1440 CheckFloat8Val(result);
1441 PG_RETURN_FLOAT8(result);
1446 * dcos - returns the cosine of arg1 (radians)
1449 dcos(PG_FUNCTION_ARGS)
1451 float8 arg1 = PG_GETARG_FLOAT8(0);
1462 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1463 errmsg("input is out of range")));
1465 CheckFloat8Val(result);
1466 PG_RETURN_FLOAT8(result);
1471 * dcot - returns the cotangent of arg1 (radians)
1474 dcot(PG_FUNCTION_ARGS)
1476 float8 arg1 = PG_GETARG_FLOAT8(0);
1481 if (errno != 0 || result == 0.0
1487 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1488 errmsg("input is out of range")));
1490 result = 1.0 / result;
1491 CheckFloat8Val(result);
1492 PG_RETURN_FLOAT8(result);
1497 * dsin - returns the sine of arg1 (radians)
1500 dsin(PG_FUNCTION_ARGS)
1502 float8 arg1 = PG_GETARG_FLOAT8(0);
1513 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1514 errmsg("input is out of range")));
1516 CheckFloat8Val(result);
1517 PG_RETURN_FLOAT8(result);
1522 * dtan - returns the tangent of arg1 (radians)
1525 dtan(PG_FUNCTION_ARGS)
1527 float8 arg1 = PG_GETARG_FLOAT8(0);
1538 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1539 errmsg("input is out of range")));
1541 CheckFloat8Val(result);
1542 PG_RETURN_FLOAT8(result);
1547 * degrees - returns degrees converted from radians
1550 degrees(PG_FUNCTION_ARGS)
1552 float8 arg1 = PG_GETARG_FLOAT8(0);
1555 result = arg1 * (180.0 / M_PI);
1557 CheckFloat8Val(result);
1558 PG_RETURN_FLOAT8(result);
1563 * dpi - returns the constant PI
1566 dpi(PG_FUNCTION_ARGS)
1568 PG_RETURN_FLOAT8(M_PI);
1573 * radians - returns radians converted from degrees
1576 radians(PG_FUNCTION_ARGS)
1578 float8 arg1 = PG_GETARG_FLOAT8(0);
1581 result = arg1 * (M_PI / 180.0);
1583 CheckFloat8Val(result);
1584 PG_RETURN_FLOAT8(result);
1589 * drandom - returns a random number
1592 drandom(PG_FUNCTION_ARGS)
1596 /* result 0.0-1.0 */
1597 result = ((double) random()) / ((double) MAX_RANDOM_VALUE);
1599 PG_RETURN_FLOAT8(result);
1604 * setseed - set seed for the random number generator
1607 setseed(PG_FUNCTION_ARGS)
1609 float8 seed = PG_GETARG_FLOAT8(0);
1610 int iseed = (int) (seed * MAX_RANDOM_VALUE);
1612 srandom((unsigned int) iseed);
1614 PG_RETURN_INT32(iseed);
1620 * =========================
1621 * FLOAT AGGREGATE OPERATORS
1622 * =========================
1624 * float8_accum - accumulate for AVG(), STDDEV(), etc
1625 * float4_accum - same, but input data is float4
1626 * float8_avg - produce final result for float AVG()
1627 * float8_variance - produce final result for float VARIANCE()
1628 * float8_stddev - produce final result for float STDDEV()
1630 * The transition datatype for all these aggregates is a 3-element array
1631 * of float8, holding the values N, sum(X), sum(X*X) in that order.
1633 * Note that we represent N as a float to avoid having to build a special
1634 * datatype. Given a reasonable floating-point implementation, there should
1635 * be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the
1636 * user will have doubtless lost interest anyway...)
1640 check_float8_array(ArrayType *transarray, const char *caller)
1643 * We expect the input to be a 3-element float array; verify that. We
1644 * don't need to use deconstruct_array() since the array data is just
1645 * going to look like a C array of 3 float8 values.
1647 if (ARR_NDIM(transarray) != 1 ||
1648 ARR_DIMS(transarray)[0] != 3 ||
1649 ARR_ELEMTYPE(transarray) != FLOAT8OID)
1650 elog(ERROR, "%s: expected 3-element float8 array", caller);
1651 return (float8 *) ARR_DATA_PTR(transarray);
1655 float8_accum(PG_FUNCTION_ARGS)
1657 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1658 float8 newval = PG_GETARG_FLOAT8(1);
1659 float8 *transvalues;
1663 Datum transdatums[3];
1666 transvalues = check_float8_array(transarray, "float8_accum");
1668 sumX = transvalues[1];
1669 sumX2 = transvalues[2];
1673 sumX2 += newval * newval;
1675 transdatums[0] = Float8GetDatumFast(N);
1676 transdatums[1] = Float8GetDatumFast(sumX);
1677 transdatums[2] = Float8GetDatumFast(sumX2);
1679 result = construct_array(transdatums, 3,
1681 sizeof(float8), false /* float8 byval */ , 'd');
1683 PG_RETURN_ARRAYTYPE_P(result);
1687 float4_accum(PG_FUNCTION_ARGS)
1689 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1690 float4 newval4 = PG_GETARG_FLOAT4(1);
1691 float8 *transvalues;
1696 Datum transdatums[3];
1699 transvalues = check_float8_array(transarray, "float4_accum");
1701 sumX = transvalues[1];
1702 sumX2 = transvalues[2];
1704 /* Do arithmetic in float8 for best accuracy */
1709 sumX2 += newval * newval;
1711 transdatums[0] = Float8GetDatumFast(N);
1712 transdatums[1] = Float8GetDatumFast(sumX);
1713 transdatums[2] = Float8GetDatumFast(sumX2);
1715 result = construct_array(transdatums, 3,
1717 sizeof(float8), false /* float8 byval */ , 'd');
1719 PG_RETURN_ARRAYTYPE_P(result);
1723 float8_avg(PG_FUNCTION_ARGS)
1725 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1726 float8 *transvalues;
1730 transvalues = check_float8_array(transarray, "float8_avg");
1732 sumX = transvalues[1];
1735 /* SQL92 defines AVG of no values to be NULL */
1739 PG_RETURN_FLOAT8(sumX / N);
1743 float8_variance(PG_FUNCTION_ARGS)
1745 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1746 float8 *transvalues;
1752 transvalues = check_float8_array(transarray, "float8_variance");
1754 sumX = transvalues[1];
1755 sumX2 = transvalues[2];
1757 /* Sample variance is undefined when N is 0 or 1, so return NULL */
1761 numerator = N * sumX2 - sumX * sumX;
1763 /* Watch out for roundoff error producing a negative numerator */
1764 if (numerator <= 0.0)
1765 PG_RETURN_FLOAT8(0.0);
1767 PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
1771 float8_stddev(PG_FUNCTION_ARGS)
1773 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1774 float8 *transvalues;
1780 transvalues = check_float8_array(transarray, "float8_stddev");
1782 sumX = transvalues[1];
1783 sumX2 = transvalues[2];
1785 /* Sample stddev is undefined when N is 0 or 1, so return NULL */
1789 numerator = N * sumX2 - sumX * sumX;
1791 /* Watch out for roundoff error producing a negative numerator */
1792 if (numerator <= 0.0)
1793 PG_RETURN_FLOAT8(0.0);
1795 PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));
1800 * ====================================
1801 * MIXED-PRECISION ARITHMETIC OPERATORS
1802 * ====================================
1806 * float48pl - returns arg1 + arg2
1807 * float48mi - returns arg1 - arg2
1808 * float48mul - returns arg1 * arg2
1809 * float48div - returns arg1 / arg2
1812 float48pl(PG_FUNCTION_ARGS)
1814 float4 arg1 = PG_GETARG_FLOAT4(0);
1815 float8 arg2 = PG_GETARG_FLOAT8(1);
1818 result = arg1 + arg2;
1819 CheckFloat8Val(result);
1820 PG_RETURN_FLOAT8(result);
1824 float48mi(PG_FUNCTION_ARGS)
1826 float4 arg1 = PG_GETARG_FLOAT4(0);
1827 float8 arg2 = PG_GETARG_FLOAT8(1);
1830 result = arg1 - arg2;
1831 CheckFloat8Val(result);
1832 PG_RETURN_FLOAT8(result);
1836 float48mul(PG_FUNCTION_ARGS)
1838 float4 arg1 = PG_GETARG_FLOAT4(0);
1839 float8 arg2 = PG_GETARG_FLOAT8(1);
1842 result = arg1 * arg2;
1843 CheckFloat8Val(result);
1844 PG_RETURN_FLOAT8(result);
1848 float48div(PG_FUNCTION_ARGS)
1850 float4 arg1 = PG_GETARG_FLOAT4(0);
1851 float8 arg2 = PG_GETARG_FLOAT8(1);
1856 (errcode(ERRCODE_DIVISION_BY_ZERO),
1857 errmsg("division by zero")));
1859 result = arg1 / arg2;
1860 CheckFloat8Val(result);
1861 PG_RETURN_FLOAT8(result);
1865 * float84pl - returns arg1 + arg2
1866 * float84mi - returns arg1 - arg2
1867 * float84mul - returns arg1 * arg2
1868 * float84div - returns arg1 / arg2
1871 float84pl(PG_FUNCTION_ARGS)
1873 float8 arg1 = PG_GETARG_FLOAT8(0);
1874 float4 arg2 = PG_GETARG_FLOAT4(1);
1877 result = arg1 + arg2;
1879 CheckFloat8Val(result);
1880 PG_RETURN_FLOAT8(result);
1884 float84mi(PG_FUNCTION_ARGS)
1886 float8 arg1 = PG_GETARG_FLOAT8(0);
1887 float4 arg2 = PG_GETARG_FLOAT4(1);
1890 result = arg1 - arg2;
1892 CheckFloat8Val(result);
1893 PG_RETURN_FLOAT8(result);
1897 float84mul(PG_FUNCTION_ARGS)
1899 float8 arg1 = PG_GETARG_FLOAT8(0);
1900 float4 arg2 = PG_GETARG_FLOAT4(1);
1903 result = arg1 * arg2;
1905 CheckFloat8Val(result);
1906 PG_RETURN_FLOAT8(result);
1910 float84div(PG_FUNCTION_ARGS)
1912 float8 arg1 = PG_GETARG_FLOAT8(0);
1913 float4 arg2 = PG_GETARG_FLOAT4(1);
1918 (errcode(ERRCODE_DIVISION_BY_ZERO),
1919 errmsg("division by zero")));
1921 result = arg1 / arg2;
1923 CheckFloat8Val(result);
1924 PG_RETURN_FLOAT8(result);
1928 * ====================
1929 * COMPARISON OPERATORS
1930 * ====================
1934 * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
1937 float48eq(PG_FUNCTION_ARGS)
1939 float4 arg1 = PG_GETARG_FLOAT4(0);
1940 float8 arg2 = PG_GETARG_FLOAT8(1);
1942 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
1946 float48ne(PG_FUNCTION_ARGS)
1948 float4 arg1 = PG_GETARG_FLOAT4(0);
1949 float8 arg2 = PG_GETARG_FLOAT8(1);
1951 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
1955 float48lt(PG_FUNCTION_ARGS)
1957 float4 arg1 = PG_GETARG_FLOAT4(0);
1958 float8 arg2 = PG_GETARG_FLOAT8(1);
1960 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
1964 float48le(PG_FUNCTION_ARGS)
1966 float4 arg1 = PG_GETARG_FLOAT4(0);
1967 float8 arg2 = PG_GETARG_FLOAT8(1);
1969 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
1973 float48gt(PG_FUNCTION_ARGS)
1975 float4 arg1 = PG_GETARG_FLOAT4(0);
1976 float8 arg2 = PG_GETARG_FLOAT8(1);
1978 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
1982 float48ge(PG_FUNCTION_ARGS)
1984 float4 arg1 = PG_GETARG_FLOAT4(0);
1985 float8 arg2 = PG_GETARG_FLOAT8(1);
1987 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
1991 * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
1994 float84eq(PG_FUNCTION_ARGS)
1996 float8 arg1 = PG_GETARG_FLOAT8(0);
1997 float4 arg2 = PG_GETARG_FLOAT4(1);
1999 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
2003 float84ne(PG_FUNCTION_ARGS)
2005 float8 arg1 = PG_GETARG_FLOAT8(0);
2006 float4 arg2 = PG_GETARG_FLOAT4(1);
2008 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
2012 float84lt(PG_FUNCTION_ARGS)
2014 float8 arg1 = PG_GETARG_FLOAT8(0);
2015 float4 arg2 = PG_GETARG_FLOAT4(1);
2017 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
2021 float84le(PG_FUNCTION_ARGS)
2023 float8 arg1 = PG_GETARG_FLOAT8(0);
2024 float4 arg2 = PG_GETARG_FLOAT4(1);
2026 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
2030 float84gt(PG_FUNCTION_ARGS)
2032 float8 arg1 = PG_GETARG_FLOAT8(0);
2033 float4 arg2 = PG_GETARG_FLOAT4(1);
2035 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
2039 float84ge(PG_FUNCTION_ARGS)
2041 float8 arg1 = PG_GETARG_FLOAT8(0);
2042 float4 arg2 = PG_GETARG_FLOAT4(1);
2044 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
2047 /* ========== PRIVATE ROUTINES ========== */
2053 int isneg = (x < 0.0);
2054 double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
2056 return isneg ? -tmpres : tmpres;
2059 #endif /* !HAVE_CBRT */