1 /*-------------------------------------------------------------------------
4 * Functions for the built-in floating-point types.
6 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/adt/float.c
13 *-------------------------------------------------------------------------
22 #include "catalog/pg_type.h"
23 #include "libpq/pqformat.h"
24 #include "utils/array.h"
25 #include "utils/builtins.h"
26 #include "utils/sortsupport.h"
30 /* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
31 #define M_PI 3.14159265358979323846
34 /* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. NAN definition from
35 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrfNotNumberNANItems.asp
37 #if defined(WIN32) && !defined(NAN)
38 static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
40 #define NAN (*(const double *) nan)
43 /* not sure what the following should be, but better to make it over-sufficient */
44 #define MAXFLOATWIDTH 64
45 #define MAXDOUBLEWIDTH 128
48 * check to see if a float4/8 val has underflowed or overflowed
50 #define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid) \
52 if (isinf(val) && !(inf_is_valid)) \
54 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
55 errmsg("value out of range: overflow"))); \
57 if ((val) == 0.0 && !(zero_is_valid)) \
59 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
60 errmsg("value out of range: underflow"))); \
64 /* ========== USER I/O ROUTINES ========== */
67 /* Configurable GUC parameter */
68 int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
71 static int float4_cmp_internal(float4 a, float4 b);
72 static int float8_cmp_internal(float8 a, float8 b);
76 * Some machines (in particular, some versions of AIX) have an extern
77 * declaration for cbrt() in <math.h> but fail to provide the actual
78 * function, which causes configure to not set HAVE_CBRT. Furthermore,
79 * their compilers spit up at the mismatch between extern declaration
80 * and static definition. We work around that here by the expedient
81 * of a #define to make the actual name of the static function different.
84 static double cbrt(double x);
85 #endif /* HAVE_CBRT */
89 * Routines to provide reasonably platform-independent handling of
90 * infinity and NaN. We assume that isinf() and isnan() are available
91 * and work per spec. (On some platforms, we have to supply our own;
92 * see src/port.) However, generating an Infinity or NaN in the first
93 * place is less well standardized; pre-C99 systems tend not to have C99's
94 * INFINITY and NAN macros. We centralize our workarounds for this here.
98 get_float8_infinity(void)
101 /* C99 standard way */
102 return (double) INFINITY;
106 * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
107 * largest normal double. We assume forcing an overflow will get us a
110 return (double) (HUGE_VAL * HUGE_VAL);
115 * The funny placements of the two #pragmas is necessary because of a
116 * long lived bug in the Microsoft compilers.
117 * See http://support.microsoft.com/kb/120968/en-us for details
119 #if (_MSC_VER >= 1800)
120 #pragma warning(disable:4756)
123 get_float4_infinity(void)
126 /* C99 standard way */
127 return (float) INFINITY;
129 #if (_MSC_VER >= 1800)
130 #pragma warning(default:4756)
134 * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
135 * largest normal double. We assume forcing an overflow will get us a
138 return (float) (HUGE_VAL * HUGE_VAL);
145 /* (double) NAN doesn't work on some NetBSD/MIPS releases */
146 #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
147 /* C99 standard way */
150 /* Assume we can get a NAN via zero divide */
151 return (double) (0.0 / 0.0);
159 /* C99 standard way */
162 /* Assume we can get a NAN via zero divide */
163 return (float) (0.0 / 0.0);
169 * Returns -1 if 'val' represents negative infinity, 1 if 'val'
170 * represents (positive) infinity, and 0 otherwise. On some platforms,
171 * this is equivalent to the isinf() macro, but not everywhere: C99
172 * does not specify that isinf() needs to distinguish between positive
173 * and negative infinity.
176 is_infinite(double val)
178 int inf = isinf(val);
190 * float4in - converts "num" to float4
193 float4in(PG_FUNCTION_ARGS)
195 char *num = PG_GETARG_CSTRING(0);
201 * endptr points to the first character _after_ the sequence we recognized
202 * as a valid floating point number. orig_num points to the original input
207 /* skip leading whitespace */
208 while (*num != '\0' && isspace((unsigned char) *num))
212 * Check for an empty-string input to begin with, to avoid the vagaries of
213 * strtod() on different platforms.
217 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
218 errmsg("invalid input syntax for type real: \"%s\"",
222 val = strtod(num, &endptr);
224 /* did we not see anything that looks like a double? */
225 if (endptr == num || errno != 0)
227 int save_errno = errno;
230 * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
231 * but not all platforms support all of these (and some accept them
232 * but set ERANGE anyway...) Therefore, we check for these inputs
233 * ourselves if strtod() fails.
235 * Note: C99 also requires hexadecimal input as well as some extended
236 * forms of NaN, but we consider these forms unportable and don't try
237 * to support them. You can use 'em if your strtod() takes 'em.
239 if (pg_strncasecmp(num, "NaN", 3) == 0)
241 val = get_float4_nan();
244 else if (pg_strncasecmp(num, "Infinity", 8) == 0)
246 val = get_float4_infinity();
249 else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
251 val = get_float4_infinity();
254 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
256 val = -get_float4_infinity();
259 else if (pg_strncasecmp(num, "inf", 3) == 0)
261 val = get_float4_infinity();
264 else if (pg_strncasecmp(num, "+inf", 4) == 0)
266 val = get_float4_infinity();
269 else if (pg_strncasecmp(num, "-inf", 4) == 0)
271 val = -get_float4_infinity();
274 else if (save_errno == ERANGE)
277 * Some platforms return ERANGE for denormalized numbers (those
278 * that are not zero, but are too close to zero to have full
279 * precision). We'd prefer not to throw error for that, so try to
280 * detect whether it's a "real" out-of-range condition by checking
281 * to see if the result is zero or huge.
283 if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
285 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
286 errmsg("\"%s\" is out of range for type real",
291 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
292 errmsg("invalid input syntax for type real: \"%s\"",
295 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
299 * Many versions of Solaris have a bug wherein strtod sets endptr to
300 * point one byte beyond the end of the string when given "inf" or
303 if (endptr != num && endptr[-1] == '\0')
306 #endif /* HAVE_BUGGY_SOLARIS_STRTOD */
308 /* skip trailing whitespace */
309 while (*endptr != '\0' && isspace((unsigned char) *endptr))
312 /* if there is any junk left at the end of the string, bail out */
315 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
316 errmsg("invalid input syntax for type real: \"%s\"",
320 * if we get here, we have a legal double, still need to check to see if
321 * it's a legal float4
323 CHECKFLOATVAL((float4) val, isinf(val), val == 0);
325 PG_RETURN_FLOAT4((float4) val);
329 * float4out - converts a float4 number to a string
330 * using a standard output format
333 float4out(PG_FUNCTION_ARGS)
335 float4 num = PG_GETARG_FLOAT4(0);
336 char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
339 PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
341 switch (is_infinite(num))
344 strcpy(ascii, "Infinity");
347 strcpy(ascii, "-Infinity");
351 int ndig = FLT_DIG + extra_float_digits;
356 snprintf(ascii, MAXFLOATWIDTH + 1, "%.*g", ndig, num);
360 PG_RETURN_CSTRING(ascii);
364 * float4recv - converts external binary format to float4
367 float4recv(PG_FUNCTION_ARGS)
369 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
371 PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));
375 * float4send - converts float4 to binary format
378 float4send(PG_FUNCTION_ARGS)
380 float4 num = PG_GETARG_FLOAT4(0);
383 pq_begintypsend(&buf);
384 pq_sendfloat4(&buf, num);
385 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
389 * float8in - converts "num" to float8
392 float8in(PG_FUNCTION_ARGS)
394 char *num = PG_GETARG_CSTRING(0);
400 * endptr points to the first character _after_ the sequence we recognized
401 * as a valid floating point number. orig_num points to the original input
406 /* skip leading whitespace */
407 while (*num != '\0' && isspace((unsigned char) *num))
411 * Check for an empty-string input to begin with, to avoid the vagaries of
412 * strtod() on different platforms.
416 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
417 errmsg("invalid input syntax for type double precision: \"%s\"",
421 val = strtod(num, &endptr);
423 /* did we not see anything that looks like a double? */
424 if (endptr == num || errno != 0)
426 int save_errno = errno;
429 * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
430 * but not all platforms support all of these (and some accept them
431 * but set ERANGE anyway...) Therefore, we check for these inputs
432 * ourselves if strtod() fails.
434 * Note: C99 also requires hexadecimal input as well as some extended
435 * forms of NaN, but we consider these forms unportable and don't try
436 * to support them. You can use 'em if your strtod() takes 'em.
438 if (pg_strncasecmp(num, "NaN", 3) == 0)
440 val = get_float8_nan();
443 else if (pg_strncasecmp(num, "Infinity", 8) == 0)
445 val = get_float8_infinity();
448 else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
450 val = get_float8_infinity();
453 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
455 val = -get_float8_infinity();
458 else if (pg_strncasecmp(num, "inf", 3) == 0)
460 val = get_float8_infinity();
463 else if (pg_strncasecmp(num, "+inf", 4) == 0)
465 val = get_float8_infinity();
468 else if (pg_strncasecmp(num, "-inf", 4) == 0)
470 val = -get_float8_infinity();
473 else if (save_errno == ERANGE)
476 * Some platforms return ERANGE for denormalized numbers (those
477 * that are not zero, but are too close to zero to have full
478 * precision). We'd prefer not to throw error for that, so try to
479 * detect whether it's a "real" out-of-range condition by checking
480 * to see if the result is zero or huge.
482 if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
484 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
485 errmsg("\"%s\" is out of range for type double precision",
490 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
491 errmsg("invalid input syntax for type double precision: \"%s\"",
494 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
498 * Many versions of Solaris have a bug wherein strtod sets endptr to
499 * point one byte beyond the end of the string when given "inf" or
502 if (endptr != num && endptr[-1] == '\0')
505 #endif /* HAVE_BUGGY_SOLARIS_STRTOD */
507 /* skip trailing whitespace */
508 while (*endptr != '\0' && isspace((unsigned char) *endptr))
511 /* if there is any junk left at the end of the string, bail out */
514 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
515 errmsg("invalid input syntax for type double precision: \"%s\"",
518 CHECKFLOATVAL(val, true, true);
520 PG_RETURN_FLOAT8(val);
524 * float8out - converts float8 number to a string
525 * using a standard output format
528 float8out(PG_FUNCTION_ARGS)
530 float8 num = PG_GETARG_FLOAT8(0);
531 char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
534 PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
536 switch (is_infinite(num))
539 strcpy(ascii, "Infinity");
542 strcpy(ascii, "-Infinity");
546 int ndig = DBL_DIG + extra_float_digits;
551 snprintf(ascii, MAXDOUBLEWIDTH + 1, "%.*g", ndig, num);
555 PG_RETURN_CSTRING(ascii);
559 * float8recv - converts external binary format to float8
562 float8recv(PG_FUNCTION_ARGS)
564 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
566 PG_RETURN_FLOAT8(pq_getmsgfloat8(buf));
570 * float8send - converts float8 to binary format
573 float8send(PG_FUNCTION_ARGS)
575 float8 num = PG_GETARG_FLOAT8(0);
578 pq_begintypsend(&buf);
579 pq_sendfloat8(&buf, num);
580 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
584 /* ========== PUBLIC ROUTINES ========== */
588 * ======================
589 * FLOAT4 BASE OPERATIONS
590 * ======================
594 * float4abs - returns |arg1| (absolute value)
597 float4abs(PG_FUNCTION_ARGS)
599 float4 arg1 = PG_GETARG_FLOAT4(0);
601 PG_RETURN_FLOAT4((float4) fabs(arg1));
605 * float4um - returns -arg1 (unary minus)
608 float4um(PG_FUNCTION_ARGS)
610 float4 arg1 = PG_GETARG_FLOAT4(0);
614 PG_RETURN_FLOAT4(result);
618 float4up(PG_FUNCTION_ARGS)
620 float4 arg = PG_GETARG_FLOAT4(0);
622 PG_RETURN_FLOAT4(arg);
626 float4larger(PG_FUNCTION_ARGS)
628 float4 arg1 = PG_GETARG_FLOAT4(0);
629 float4 arg2 = PG_GETARG_FLOAT4(1);
632 if (float4_cmp_internal(arg1, arg2) > 0)
636 PG_RETURN_FLOAT4(result);
640 float4smaller(PG_FUNCTION_ARGS)
642 float4 arg1 = PG_GETARG_FLOAT4(0);
643 float4 arg2 = PG_GETARG_FLOAT4(1);
646 if (float4_cmp_internal(arg1, arg2) < 0)
650 PG_RETURN_FLOAT4(result);
654 * ======================
655 * FLOAT8 BASE OPERATIONS
656 * ======================
660 * float8abs - returns |arg1| (absolute value)
663 float8abs(PG_FUNCTION_ARGS)
665 float8 arg1 = PG_GETARG_FLOAT8(0);
667 PG_RETURN_FLOAT8(fabs(arg1));
672 * float8um - returns -arg1 (unary minus)
675 float8um(PG_FUNCTION_ARGS)
677 float8 arg1 = PG_GETARG_FLOAT8(0);
681 PG_RETURN_FLOAT8(result);
685 float8up(PG_FUNCTION_ARGS)
687 float8 arg = PG_GETARG_FLOAT8(0);
689 PG_RETURN_FLOAT8(arg);
693 float8larger(PG_FUNCTION_ARGS)
695 float8 arg1 = PG_GETARG_FLOAT8(0);
696 float8 arg2 = PG_GETARG_FLOAT8(1);
699 if (float8_cmp_internal(arg1, arg2) > 0)
703 PG_RETURN_FLOAT8(result);
707 float8smaller(PG_FUNCTION_ARGS)
709 float8 arg1 = PG_GETARG_FLOAT8(0);
710 float8 arg2 = PG_GETARG_FLOAT8(1);
713 if (float8_cmp_internal(arg1, arg2) < 0)
717 PG_RETURN_FLOAT8(result);
722 * ====================
723 * ARITHMETIC OPERATORS
724 * ====================
728 * float4pl - returns arg1 + arg2
729 * float4mi - returns arg1 - arg2
730 * float4mul - returns arg1 * arg2
731 * float4div - returns arg1 / arg2
734 float4pl(PG_FUNCTION_ARGS)
736 float4 arg1 = PG_GETARG_FLOAT4(0);
737 float4 arg2 = PG_GETARG_FLOAT4(1);
740 result = arg1 + arg2;
743 * There isn't any way to check for underflow of addition/subtraction
744 * because numbers near the underflow value have already been rounded to
745 * the point where we can't detect that the two values were originally
746 * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
749 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
750 PG_RETURN_FLOAT4(result);
754 float4mi(PG_FUNCTION_ARGS)
756 float4 arg1 = PG_GETARG_FLOAT4(0);
757 float4 arg2 = PG_GETARG_FLOAT4(1);
760 result = arg1 - arg2;
761 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
762 PG_RETURN_FLOAT4(result);
766 float4mul(PG_FUNCTION_ARGS)
768 float4 arg1 = PG_GETARG_FLOAT4(0);
769 float4 arg2 = PG_GETARG_FLOAT4(1);
772 result = arg1 * arg2;
773 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
774 arg1 == 0 || arg2 == 0);
775 PG_RETURN_FLOAT4(result);
779 float4div(PG_FUNCTION_ARGS)
781 float4 arg1 = PG_GETARG_FLOAT4(0);
782 float4 arg2 = PG_GETARG_FLOAT4(1);
787 (errcode(ERRCODE_DIVISION_BY_ZERO),
788 errmsg("division by zero")));
790 result = arg1 / arg2;
792 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
793 PG_RETURN_FLOAT4(result);
797 * float8pl - returns arg1 + arg2
798 * float8mi - returns arg1 - arg2
799 * float8mul - returns arg1 * arg2
800 * float8div - returns arg1 / arg2
803 float8pl(PG_FUNCTION_ARGS)
805 float8 arg1 = PG_GETARG_FLOAT8(0);
806 float8 arg2 = PG_GETARG_FLOAT8(1);
809 result = arg1 + arg2;
811 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
812 PG_RETURN_FLOAT8(result);
816 float8mi(PG_FUNCTION_ARGS)
818 float8 arg1 = PG_GETARG_FLOAT8(0);
819 float8 arg2 = PG_GETARG_FLOAT8(1);
822 result = arg1 - arg2;
824 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
825 PG_RETURN_FLOAT8(result);
829 float8mul(PG_FUNCTION_ARGS)
831 float8 arg1 = PG_GETARG_FLOAT8(0);
832 float8 arg2 = PG_GETARG_FLOAT8(1);
835 result = arg1 * arg2;
837 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
838 arg1 == 0 || arg2 == 0);
839 PG_RETURN_FLOAT8(result);
843 float8div(PG_FUNCTION_ARGS)
845 float8 arg1 = PG_GETARG_FLOAT8(0);
846 float8 arg2 = PG_GETARG_FLOAT8(1);
851 (errcode(ERRCODE_DIVISION_BY_ZERO),
852 errmsg("division by zero")));
854 result = arg1 / arg2;
856 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
857 PG_RETURN_FLOAT8(result);
862 * ====================
863 * COMPARISON OPERATORS
864 * ====================
868 * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
871 float4_cmp_internal(float4 a, float4 b)
874 * We consider all NANs to be equal and larger than any non-NAN. This is
875 * somewhat arbitrary; the important thing is to have a consistent sort
881 return 0; /* NAN = NAN */
883 return 1; /* NAN > non-NAN */
887 return -1; /* non-NAN < NAN */
901 float4eq(PG_FUNCTION_ARGS)
903 float4 arg1 = PG_GETARG_FLOAT4(0);
904 float4 arg2 = PG_GETARG_FLOAT4(1);
906 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);
910 float4ne(PG_FUNCTION_ARGS)
912 float4 arg1 = PG_GETARG_FLOAT4(0);
913 float4 arg2 = PG_GETARG_FLOAT4(1);
915 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);
919 float4lt(PG_FUNCTION_ARGS)
921 float4 arg1 = PG_GETARG_FLOAT4(0);
922 float4 arg2 = PG_GETARG_FLOAT4(1);
924 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);
928 float4le(PG_FUNCTION_ARGS)
930 float4 arg1 = PG_GETARG_FLOAT4(0);
931 float4 arg2 = PG_GETARG_FLOAT4(1);
933 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);
937 float4gt(PG_FUNCTION_ARGS)
939 float4 arg1 = PG_GETARG_FLOAT4(0);
940 float4 arg2 = PG_GETARG_FLOAT4(1);
942 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);
946 float4ge(PG_FUNCTION_ARGS)
948 float4 arg1 = PG_GETARG_FLOAT4(0);
949 float4 arg2 = PG_GETARG_FLOAT4(1);
951 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);
955 btfloat4cmp(PG_FUNCTION_ARGS)
957 float4 arg1 = PG_GETARG_FLOAT4(0);
958 float4 arg2 = PG_GETARG_FLOAT4(1);
960 PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
964 btfloat4fastcmp(Datum x, Datum y, SortSupport ssup)
966 float4 arg1 = DatumGetFloat4(x);
967 float4 arg2 = DatumGetFloat4(y);
969 return float4_cmp_internal(arg1, arg2);
973 btfloat4sortsupport(PG_FUNCTION_ARGS)
975 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
977 ssup->comparator = btfloat4fastcmp;
982 * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
985 float8_cmp_internal(float8 a, float8 b)
988 * We consider all NANs to be equal and larger than any non-NAN. This is
989 * somewhat arbitrary; the important thing is to have a consistent sort
995 return 0; /* NAN = NAN */
997 return 1; /* NAN > non-NAN */
1001 return -1; /* non-NAN < NAN */
1015 float8eq(PG_FUNCTION_ARGS)
1017 float8 arg1 = PG_GETARG_FLOAT8(0);
1018 float8 arg2 = PG_GETARG_FLOAT8(1);
1020 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
1024 float8ne(PG_FUNCTION_ARGS)
1026 float8 arg1 = PG_GETARG_FLOAT8(0);
1027 float8 arg2 = PG_GETARG_FLOAT8(1);
1029 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
1033 float8lt(PG_FUNCTION_ARGS)
1035 float8 arg1 = PG_GETARG_FLOAT8(0);
1036 float8 arg2 = PG_GETARG_FLOAT8(1);
1038 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
1042 float8le(PG_FUNCTION_ARGS)
1044 float8 arg1 = PG_GETARG_FLOAT8(0);
1045 float8 arg2 = PG_GETARG_FLOAT8(1);
1047 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
1051 float8gt(PG_FUNCTION_ARGS)
1053 float8 arg1 = PG_GETARG_FLOAT8(0);
1054 float8 arg2 = PG_GETARG_FLOAT8(1);
1056 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
1060 float8ge(PG_FUNCTION_ARGS)
1062 float8 arg1 = PG_GETARG_FLOAT8(0);
1063 float8 arg2 = PG_GETARG_FLOAT8(1);
1065 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
1069 btfloat8cmp(PG_FUNCTION_ARGS)
1071 float8 arg1 = PG_GETARG_FLOAT8(0);
1072 float8 arg2 = PG_GETARG_FLOAT8(1);
1074 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1078 btfloat8fastcmp(Datum x, Datum y, SortSupport ssup)
1080 float8 arg1 = DatumGetFloat8(x);
1081 float8 arg2 = DatumGetFloat8(y);
1083 return float8_cmp_internal(arg1, arg2);
1087 btfloat8sortsupport(PG_FUNCTION_ARGS)
1089 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
1091 ssup->comparator = btfloat8fastcmp;
1096 btfloat48cmp(PG_FUNCTION_ARGS)
1098 float4 arg1 = PG_GETARG_FLOAT4(0);
1099 float8 arg2 = PG_GETARG_FLOAT8(1);
1101 /* widen float4 to float8 and then compare */
1102 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1106 btfloat84cmp(PG_FUNCTION_ARGS)
1108 float8 arg1 = PG_GETARG_FLOAT8(0);
1109 float4 arg2 = PG_GETARG_FLOAT4(1);
1111 /* widen float4 to float8 and then compare */
1112 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1117 * ===================
1118 * CONVERSION ROUTINES
1119 * ===================
1123 * ftod - converts a float4 number to a float8 number
1126 ftod(PG_FUNCTION_ARGS)
1128 float4 num = PG_GETARG_FLOAT4(0);
1130 PG_RETURN_FLOAT8((float8) num);
1135 * dtof - converts a float8 number to a float4 number
1138 dtof(PG_FUNCTION_ARGS)
1140 float8 num = PG_GETARG_FLOAT8(0);
1142 CHECKFLOATVAL((float4) num, isinf(num), num == 0);
1144 PG_RETURN_FLOAT4((float4) num);
1149 * dtoi4 - converts a float8 number to an int4 number
1152 dtoi4(PG_FUNCTION_ARGS)
1154 float8 num = PG_GETARG_FLOAT8(0);
1157 /* 'Inf' is handled by INT_MAX */
1158 if (num < INT_MIN || num > INT_MAX || isnan(num))
1160 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1161 errmsg("integer out of range")));
1163 result = (int32) rint(num);
1164 PG_RETURN_INT32(result);
1169 * dtoi2 - converts a float8 number to an int2 number
1172 dtoi2(PG_FUNCTION_ARGS)
1174 float8 num = PG_GETARG_FLOAT8(0);
1176 if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
1178 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1179 errmsg("smallint out of range")));
1181 PG_RETURN_INT16((int16) rint(num));
1186 * i4tod - converts an int4 number to a float8 number
1189 i4tod(PG_FUNCTION_ARGS)
1191 int32 num = PG_GETARG_INT32(0);
1193 PG_RETURN_FLOAT8((float8) num);
1198 * i2tod - converts an int2 number to a float8 number
1201 i2tod(PG_FUNCTION_ARGS)
1203 int16 num = PG_GETARG_INT16(0);
1205 PG_RETURN_FLOAT8((float8) num);
1210 * ftoi4 - converts a float4 number to an int4 number
1213 ftoi4(PG_FUNCTION_ARGS)
1215 float4 num = PG_GETARG_FLOAT4(0);
1217 if (num < INT_MIN || num > INT_MAX || isnan(num))
1219 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1220 errmsg("integer out of range")));
1222 PG_RETURN_INT32((int32) rint(num));
1227 * ftoi2 - converts a float4 number to an int2 number
1230 ftoi2(PG_FUNCTION_ARGS)
1232 float4 num = PG_GETARG_FLOAT4(0);
1234 if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
1236 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1237 errmsg("smallint out of range")));
1239 PG_RETURN_INT16((int16) rint(num));
1244 * i4tof - converts an int4 number to a float4 number
1247 i4tof(PG_FUNCTION_ARGS)
1249 int32 num = PG_GETARG_INT32(0);
1251 PG_RETURN_FLOAT4((float4) num);
1256 * i2tof - converts an int2 number to a float4 number
1259 i2tof(PG_FUNCTION_ARGS)
1261 int16 num = PG_GETARG_INT16(0);
1263 PG_RETURN_FLOAT4((float4) num);
1268 * =======================
1269 * RANDOM FLOAT8 OPERATORS
1270 * =======================
1274 * dround - returns ROUND(arg1)
1277 dround(PG_FUNCTION_ARGS)
1279 float8 arg1 = PG_GETARG_FLOAT8(0);
1281 PG_RETURN_FLOAT8(rint(arg1));
1285 * dceil - returns the smallest integer greater than or
1286 * equal to the specified float
1289 dceil(PG_FUNCTION_ARGS)
1291 float8 arg1 = PG_GETARG_FLOAT8(0);
1293 PG_RETURN_FLOAT8(ceil(arg1));
1297 * dfloor - returns the largest integer lesser than or
1298 * equal to the specified float
1301 dfloor(PG_FUNCTION_ARGS)
1303 float8 arg1 = PG_GETARG_FLOAT8(0);
1305 PG_RETURN_FLOAT8(floor(arg1));
1309 * dsign - returns -1 if the argument is less than 0, 0
1310 * if the argument is equal to 0, and 1 if the
1311 * argument is greater than zero.
1314 dsign(PG_FUNCTION_ARGS)
1316 float8 arg1 = PG_GETARG_FLOAT8(0);
1326 PG_RETURN_FLOAT8(result);
1330 * dtrunc - returns truncation-towards-zero of arg1,
1331 * arg1 >= 0 ... the greatest integer less
1332 * than or equal to arg1
1333 * arg1 < 0 ... the least integer greater
1334 * than or equal to arg1
1337 dtrunc(PG_FUNCTION_ARGS)
1339 float8 arg1 = PG_GETARG_FLOAT8(0);
1343 result = floor(arg1);
1345 result = -floor(-arg1);
1347 PG_RETURN_FLOAT8(result);
1352 * dsqrt - returns square root of arg1
1355 dsqrt(PG_FUNCTION_ARGS)
1357 float8 arg1 = PG_GETARG_FLOAT8(0);
1362 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1363 errmsg("cannot take square root of a negative number")));
1365 result = sqrt(arg1);
1367 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1368 PG_RETURN_FLOAT8(result);
1373 * dcbrt - returns cube root of arg1
1376 dcbrt(PG_FUNCTION_ARGS)
1378 float8 arg1 = PG_GETARG_FLOAT8(0);
1381 result = cbrt(arg1);
1382 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1383 PG_RETURN_FLOAT8(result);
1388 * dpow - returns pow(arg1,arg2)
1391 dpow(PG_FUNCTION_ARGS)
1393 float8 arg1 = PG_GETARG_FLOAT8(0);
1394 float8 arg2 = PG_GETARG_FLOAT8(1);
1398 * The SQL spec requires that we emit a particular SQLSTATE error code for
1399 * certain error conditions. Specifically, we don't return a
1400 * divide-by-zero error code for 0 ^ -1.
1402 if (arg1 == 0 && arg2 < 0)
1404 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1405 errmsg("zero raised to a negative power is undefined")));
1406 if (arg1 < 0 && floor(arg2) != arg2)
1408 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1409 errmsg("a negative number raised to a non-integer power yields a complex result")));
1412 * pow() sets errno only on some platforms, depending on whether it
1413 * follows _IEEE_, _POSIX_, _XOPEN_, or _SVID_, so we try to avoid using
1414 * errno. However, some platform/CPU combinations return errno == EDOM
1415 * and result == Nan for negative arg1 and very large arg2 (they must be
1416 * using something different from our floor() test to decide it's
1417 * invalid). Other platforms (HPPA) return errno == ERANGE and a large
1418 * (HUGE_VAL) but finite result to signal overflow.
1421 result = pow(arg1, arg2);
1422 if (errno == EDOM && isnan(result))
1424 if ((fabs(arg1) > 1 && arg2 >= 0) || (fabs(arg1) < 1 && arg2 < 0))
1425 /* The sign of Inf is not significant in this case. */
1426 result = get_float8_infinity();
1427 else if (fabs(arg1) != 1)
1432 else if (errno == ERANGE && result != 0 && !isinf(result))
1433 result = get_float8_infinity();
1435 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
1436 PG_RETURN_FLOAT8(result);
1441 * dexp - returns the exponential function of arg1
1444 dexp(PG_FUNCTION_ARGS)
1446 float8 arg1 = PG_GETARG_FLOAT8(0);
1451 if (errno == ERANGE && result != 0 && !isinf(result))
1452 result = get_float8_infinity();
1454 CHECKFLOATVAL(result, isinf(arg1), false);
1455 PG_RETURN_FLOAT8(result);
1460 * dlog1 - returns the natural logarithm of arg1
1463 dlog1(PG_FUNCTION_ARGS)
1465 float8 arg1 = PG_GETARG_FLOAT8(0);
1469 * Emit particular SQLSTATE error codes for ln(). This is required by the
1474 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1475 errmsg("cannot take logarithm of zero")));
1478 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1479 errmsg("cannot take logarithm of a negative number")));
1483 CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
1484 PG_RETURN_FLOAT8(result);
1489 * dlog10 - returns the base 10 logarithm of arg1
1492 dlog10(PG_FUNCTION_ARGS)
1494 float8 arg1 = PG_GETARG_FLOAT8(0);
1498 * Emit particular SQLSTATE error codes for log(). The SQL spec doesn't
1499 * define log(), but it does define ln(), so it makes sense to emit the
1500 * same error code for an analogous error condition.
1504 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1505 errmsg("cannot take logarithm of zero")));
1508 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1509 errmsg("cannot take logarithm of a negative number")));
1511 result = log10(arg1);
1513 CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
1514 PG_RETURN_FLOAT8(result);
1519 * dacos - returns the arccos of arg1 (radians)
1522 dacos(PG_FUNCTION_ARGS)
1524 float8 arg1 = PG_GETARG_FLOAT8(0);
1528 * We use errno here because the trigonometric functions are cyclic and
1529 * hard to check for underflow.
1532 result = acos(arg1);
1535 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1536 errmsg("input is out of range")));
1538 CHECKFLOATVAL(result, isinf(arg1), true);
1539 PG_RETURN_FLOAT8(result);
1544 * dasin - returns the arcsin of arg1 (radians)
1547 dasin(PG_FUNCTION_ARGS)
1549 float8 arg1 = PG_GETARG_FLOAT8(0);
1553 result = asin(arg1);
1556 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1557 errmsg("input is out of range")));
1559 CHECKFLOATVAL(result, isinf(arg1), true);
1560 PG_RETURN_FLOAT8(result);
1565 * datan - returns the arctan of arg1 (radians)
1568 datan(PG_FUNCTION_ARGS)
1570 float8 arg1 = PG_GETARG_FLOAT8(0);
1574 result = atan(arg1);
1577 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1578 errmsg("input is out of range")));
1580 CHECKFLOATVAL(result, isinf(arg1), true);
1581 PG_RETURN_FLOAT8(result);
1586 * atan2 - returns the arctan2 of arg1 (radians)
1589 datan2(PG_FUNCTION_ARGS)
1591 float8 arg1 = PG_GETARG_FLOAT8(0);
1592 float8 arg2 = PG_GETARG_FLOAT8(1);
1596 result = atan2(arg1, arg2);
1599 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1600 errmsg("input is out of range")));
1602 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
1603 PG_RETURN_FLOAT8(result);
1608 * dcos - returns the cosine of arg1 (radians)
1611 dcos(PG_FUNCTION_ARGS)
1613 float8 arg1 = PG_GETARG_FLOAT8(0);
1620 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1621 errmsg("input is out of range")));
1623 CHECKFLOATVAL(result, isinf(arg1), true);
1624 PG_RETURN_FLOAT8(result);
1629 * dcot - returns the cotangent of arg1 (radians)
1632 dcot(PG_FUNCTION_ARGS)
1634 float8 arg1 = PG_GETARG_FLOAT8(0);
1641 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1642 errmsg("input is out of range")));
1644 result = 1.0 / result;
1645 CHECKFLOATVAL(result, true /* cotan(pi/2) == inf */ , true);
1646 PG_RETURN_FLOAT8(result);
1651 * dsin - returns the sine of arg1 (radians)
1654 dsin(PG_FUNCTION_ARGS)
1656 float8 arg1 = PG_GETARG_FLOAT8(0);
1663 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1664 errmsg("input is out of range")));
1666 CHECKFLOATVAL(result, isinf(arg1), true);
1667 PG_RETURN_FLOAT8(result);
1672 * dtan - returns the tangent of arg1 (radians)
1675 dtan(PG_FUNCTION_ARGS)
1677 float8 arg1 = PG_GETARG_FLOAT8(0);
1684 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1685 errmsg("input is out of range")));
1687 CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */ , true);
1688 PG_RETURN_FLOAT8(result);
1693 * degrees - returns degrees converted from radians
1696 degrees(PG_FUNCTION_ARGS)
1698 float8 arg1 = PG_GETARG_FLOAT8(0);
1701 result = arg1 * (180.0 / M_PI);
1703 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1704 PG_RETURN_FLOAT8(result);
1709 * dpi - returns the constant PI
1712 dpi(PG_FUNCTION_ARGS)
1714 PG_RETURN_FLOAT8(M_PI);
1719 * radians - returns radians converted from degrees
1722 radians(PG_FUNCTION_ARGS)
1724 float8 arg1 = PG_GETARG_FLOAT8(0);
1727 result = arg1 * (M_PI / 180.0);
1729 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1730 PG_RETURN_FLOAT8(result);
1735 * drandom - returns a random number
1738 drandom(PG_FUNCTION_ARGS)
1742 /* result [0.0 - 1.0) */
1743 result = (double) random() / ((double) MAX_RANDOM_VALUE + 1);
1745 PG_RETURN_FLOAT8(result);
1750 * setseed - set seed for the random number generator
1753 setseed(PG_FUNCTION_ARGS)
1755 float8 seed = PG_GETARG_FLOAT8(0);
1758 if (seed < -1 || seed > 1)
1759 elog(ERROR, "setseed parameter %f out of range [-1,1]", seed);
1761 iseed = (int) (seed * MAX_RANDOM_VALUE);
1762 srandom((unsigned int) iseed);
1770 * =========================
1771 * FLOAT AGGREGATE OPERATORS
1772 * =========================
1774 * float8_accum - accumulate for AVG(), variance aggregates, etc.
1775 * float4_accum - same, but input data is float4
1776 * float8_avg - produce final result for float AVG()
1777 * float8_var_samp - produce final result for float VAR_SAMP()
1778 * float8_var_pop - produce final result for float VAR_POP()
1779 * float8_stddev_samp - produce final result for float STDDEV_SAMP()
1780 * float8_stddev_pop - produce final result for float STDDEV_POP()
1782 * The transition datatype for all these aggregates is a 3-element array
1783 * of float8, holding the values N, sum(X), sum(X*X) in that order.
1785 * Note that we represent N as a float to avoid having to build a special
1786 * datatype. Given a reasonable floating-point implementation, there should
1787 * be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the
1788 * user will have doubtless lost interest anyway...)
1792 check_float8_array(ArrayType *transarray, const char *caller, int n)
1795 * We expect the input to be an N-element float array; verify that. We
1796 * don't need to use deconstruct_array() since the array data is just
1797 * going to look like a C array of N float8 values.
1799 if (ARR_NDIM(transarray) != 1 ||
1800 ARR_DIMS(transarray)[0] != n ||
1801 ARR_HASNULL(transarray) ||
1802 ARR_ELEMTYPE(transarray) != FLOAT8OID)
1803 elog(ERROR, "%s: expected %d-element float8 array", caller, n);
1804 return (float8 *) ARR_DATA_PTR(transarray);
1808 float8_accum(PG_FUNCTION_ARGS)
1810 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1811 float8 newval = PG_GETARG_FLOAT8(1);
1812 float8 *transvalues;
1817 transvalues = check_float8_array(transarray, "float8_accum", 3);
1819 sumX = transvalues[1];
1820 sumX2 = transvalues[2];
1824 CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
1825 sumX2 += newval * newval;
1826 CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
1829 * If we're invoked as an aggregate, we can cheat and modify our first
1830 * parameter in-place to reduce palloc overhead. Otherwise we construct a
1831 * new array with the updated transition data and return it.
1833 if (AggCheckCallContext(fcinfo, NULL))
1836 transvalues[1] = sumX;
1837 transvalues[2] = sumX2;
1839 PG_RETURN_ARRAYTYPE_P(transarray);
1843 Datum transdatums[3];
1846 transdatums[0] = Float8GetDatumFast(N);
1847 transdatums[1] = Float8GetDatumFast(sumX);
1848 transdatums[2] = Float8GetDatumFast(sumX2);
1850 result = construct_array(transdatums, 3,
1852 sizeof(float8), FLOAT8PASSBYVAL, 'd');
1854 PG_RETURN_ARRAYTYPE_P(result);
1859 float4_accum(PG_FUNCTION_ARGS)
1861 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1863 /* do computations as float8 */
1864 float8 newval = PG_GETARG_FLOAT4(1);
1865 float8 *transvalues;
1870 transvalues = check_float8_array(transarray, "float4_accum", 3);
1872 sumX = transvalues[1];
1873 sumX2 = transvalues[2];
1877 CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
1878 sumX2 += newval * newval;
1879 CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
1882 * If we're invoked as an aggregate, we can cheat and modify our first
1883 * parameter in-place to reduce palloc overhead. Otherwise we construct a
1884 * new array with the updated transition data and return it.
1886 if (AggCheckCallContext(fcinfo, NULL))
1889 transvalues[1] = sumX;
1890 transvalues[2] = sumX2;
1892 PG_RETURN_ARRAYTYPE_P(transarray);
1896 Datum transdatums[3];
1899 transdatums[0] = Float8GetDatumFast(N);
1900 transdatums[1] = Float8GetDatumFast(sumX);
1901 transdatums[2] = Float8GetDatumFast(sumX2);
1903 result = construct_array(transdatums, 3,
1905 sizeof(float8), FLOAT8PASSBYVAL, 'd');
1907 PG_RETURN_ARRAYTYPE_P(result);
1912 float8_avg(PG_FUNCTION_ARGS)
1914 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1915 float8 *transvalues;
1919 transvalues = check_float8_array(transarray, "float8_avg", 3);
1921 sumX = transvalues[1];
1924 /* SQL defines AVG of no values to be NULL */
1928 PG_RETURN_FLOAT8(sumX / N);
1932 float8_var_pop(PG_FUNCTION_ARGS)
1934 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1935 float8 *transvalues;
1941 transvalues = check_float8_array(transarray, "float8_var_pop", 3);
1943 sumX = transvalues[1];
1944 sumX2 = transvalues[2];
1946 /* Population variance is undefined when N is 0, so return NULL */
1950 numerator = N * sumX2 - sumX * sumX;
1951 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
1953 /* Watch out for roundoff error producing a negative numerator */
1954 if (numerator <= 0.0)
1955 PG_RETURN_FLOAT8(0.0);
1957 PG_RETURN_FLOAT8(numerator / (N * N));
1961 float8_var_samp(PG_FUNCTION_ARGS)
1963 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1964 float8 *transvalues;
1970 transvalues = check_float8_array(transarray, "float8_var_samp", 3);
1972 sumX = transvalues[1];
1973 sumX2 = transvalues[2];
1975 /* Sample variance is undefined when N is 0 or 1, so return NULL */
1979 numerator = N * sumX2 - sumX * sumX;
1980 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
1982 /* Watch out for roundoff error producing a negative numerator */
1983 if (numerator <= 0.0)
1984 PG_RETURN_FLOAT8(0.0);
1986 PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
1990 float8_stddev_pop(PG_FUNCTION_ARGS)
1992 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1993 float8 *transvalues;
1999 transvalues = check_float8_array(transarray, "float8_stddev_pop", 3);
2001 sumX = transvalues[1];
2002 sumX2 = transvalues[2];
2004 /* Population stddev is undefined when N is 0, so return NULL */
2008 numerator = N * sumX2 - sumX * sumX;
2009 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2011 /* Watch out for roundoff error producing a negative numerator */
2012 if (numerator <= 0.0)
2013 PG_RETURN_FLOAT8(0.0);
2015 PG_RETURN_FLOAT8(sqrt(numerator / (N * N)));
2019 float8_stddev_samp(PG_FUNCTION_ARGS)
2021 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2022 float8 *transvalues;
2028 transvalues = check_float8_array(transarray, "float8_stddev_samp", 3);
2030 sumX = transvalues[1];
2031 sumX2 = transvalues[2];
2033 /* Sample stddev is undefined when N is 0 or 1, so return NULL */
2037 numerator = N * sumX2 - sumX * sumX;
2038 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2040 /* Watch out for roundoff error producing a negative numerator */
2041 if (numerator <= 0.0)
2042 PG_RETURN_FLOAT8(0.0);
2044 PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));
2048 * =========================
2049 * SQL2003 BINARY AGGREGATES
2050 * =========================
2052 * The transition datatype for all these aggregates is a 6-element array of
2053 * float8, holding the values N, sum(X), sum(X*X), sum(Y), sum(Y*Y), sum(X*Y)
2054 * in that order. Note that Y is the first argument to the aggregates!
2056 * It might seem attractive to optimize this by having multiple accumulator
2057 * functions that only calculate the sums actually needed. But on most
2058 * modern machines, a couple of extra floating-point multiplies will be
2059 * insignificant compared to the other per-tuple overhead, so I've chosen
2060 * to minimize code space instead.
2064 float8_regr_accum(PG_FUNCTION_ARGS)
2066 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2067 float8 newvalY = PG_GETARG_FLOAT8(1);
2068 float8 newvalX = PG_GETARG_FLOAT8(2);
2069 float8 *transvalues;
2077 transvalues = check_float8_array(transarray, "float8_regr_accum", 6);
2079 sumX = transvalues[1];
2080 sumX2 = transvalues[2];
2081 sumY = transvalues[3];
2082 sumY2 = transvalues[4];
2083 sumXY = transvalues[5];
2087 CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newvalX), true);
2088 sumX2 += newvalX * newvalX;
2089 CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newvalX), true);
2091 CHECKFLOATVAL(sumY, isinf(transvalues[3]) || isinf(newvalY), true);
2092 sumY2 += newvalY * newvalY;
2093 CHECKFLOATVAL(sumY2, isinf(transvalues[4]) || isinf(newvalY), true);
2094 sumXY += newvalX * newvalY;
2095 CHECKFLOATVAL(sumXY, isinf(transvalues[5]) || isinf(newvalX) ||
2096 isinf(newvalY), true);
2099 * If we're invoked as an aggregate, we can cheat and modify our first
2100 * parameter in-place to reduce palloc overhead. Otherwise we construct a
2101 * new array with the updated transition data and return it.
2103 if (AggCheckCallContext(fcinfo, NULL))
2106 transvalues[1] = sumX;
2107 transvalues[2] = sumX2;
2108 transvalues[3] = sumY;
2109 transvalues[4] = sumY2;
2110 transvalues[5] = sumXY;
2112 PG_RETURN_ARRAYTYPE_P(transarray);
2116 Datum transdatums[6];
2119 transdatums[0] = Float8GetDatumFast(N);
2120 transdatums[1] = Float8GetDatumFast(sumX);
2121 transdatums[2] = Float8GetDatumFast(sumX2);
2122 transdatums[3] = Float8GetDatumFast(sumY);
2123 transdatums[4] = Float8GetDatumFast(sumY2);
2124 transdatums[5] = Float8GetDatumFast(sumXY);
2126 result = construct_array(transdatums, 6,
2128 sizeof(float8), FLOAT8PASSBYVAL, 'd');
2130 PG_RETURN_ARRAYTYPE_P(result);
2135 float8_regr_sxx(PG_FUNCTION_ARGS)
2137 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2138 float8 *transvalues;
2144 transvalues = check_float8_array(transarray, "float8_regr_sxx", 6);
2146 sumX = transvalues[1];
2147 sumX2 = transvalues[2];
2149 /* if N is 0 we should return NULL */
2153 numerator = N * sumX2 - sumX * sumX;
2154 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2156 /* Watch out for roundoff error producing a negative numerator */
2157 if (numerator <= 0.0)
2158 PG_RETURN_FLOAT8(0.0);
2160 PG_RETURN_FLOAT8(numerator / N);
2164 float8_regr_syy(PG_FUNCTION_ARGS)
2166 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2167 float8 *transvalues;
2173 transvalues = check_float8_array(transarray, "float8_regr_syy", 6);
2175 sumY = transvalues[3];
2176 sumY2 = transvalues[4];
2178 /* if N is 0 we should return NULL */
2182 numerator = N * sumY2 - sumY * sumY;
2183 CHECKFLOATVAL(numerator, isinf(sumY2) || isinf(sumY), true);
2185 /* Watch out for roundoff error producing a negative numerator */
2186 if (numerator <= 0.0)
2187 PG_RETURN_FLOAT8(0.0);
2189 PG_RETURN_FLOAT8(numerator / N);
2193 float8_regr_sxy(PG_FUNCTION_ARGS)
2195 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2196 float8 *transvalues;
2203 transvalues = check_float8_array(transarray, "float8_regr_sxy", 6);
2205 sumX = transvalues[1];
2206 sumY = transvalues[3];
2207 sumXY = transvalues[5];
2209 /* if N is 0 we should return NULL */
2213 numerator = N * sumXY - sumX * sumY;
2214 CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
2217 /* A negative result is valid here */
2219 PG_RETURN_FLOAT8(numerator / N);
2223 float8_regr_avgx(PG_FUNCTION_ARGS)
2225 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2226 float8 *transvalues;
2230 transvalues = check_float8_array(transarray, "float8_regr_avgx", 6);
2232 sumX = transvalues[1];
2234 /* if N is 0 we should return NULL */
2238 PG_RETURN_FLOAT8(sumX / N);
2242 float8_regr_avgy(PG_FUNCTION_ARGS)
2244 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2245 float8 *transvalues;
2249 transvalues = check_float8_array(transarray, "float8_regr_avgy", 6);
2251 sumY = transvalues[3];
2253 /* if N is 0 we should return NULL */
2257 PG_RETURN_FLOAT8(sumY / N);
2261 float8_covar_pop(PG_FUNCTION_ARGS)
2263 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2264 float8 *transvalues;
2271 transvalues = check_float8_array(transarray, "float8_covar_pop", 6);
2273 sumX = transvalues[1];
2274 sumY = transvalues[3];
2275 sumXY = transvalues[5];
2277 /* if N is 0 we should return NULL */
2281 numerator = N * sumXY - sumX * sumY;
2282 CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
2285 PG_RETURN_FLOAT8(numerator / (N * N));
2289 float8_covar_samp(PG_FUNCTION_ARGS)
2291 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2292 float8 *transvalues;
2299 transvalues = check_float8_array(transarray, "float8_covar_samp", 6);
2301 sumX = transvalues[1];
2302 sumY = transvalues[3];
2303 sumXY = transvalues[5];
2305 /* if N is <= 1 we should return NULL */
2309 numerator = N * sumXY - sumX * sumY;
2310 CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
2313 PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
2317 float8_corr(PG_FUNCTION_ARGS)
2319 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2320 float8 *transvalues;
2331 transvalues = check_float8_array(transarray, "float8_corr", 6);
2333 sumX = transvalues[1];
2334 sumX2 = transvalues[2];
2335 sumY = transvalues[3];
2336 sumY2 = transvalues[4];
2337 sumXY = transvalues[5];
2339 /* if N is 0 we should return NULL */
2343 numeratorX = N * sumX2 - sumX * sumX;
2344 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
2345 numeratorY = N * sumY2 - sumY * sumY;
2346 CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
2347 numeratorXY = N * sumXY - sumX * sumY;
2348 CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
2350 if (numeratorX <= 0 || numeratorY <= 0)
2353 PG_RETURN_FLOAT8(numeratorXY / sqrt(numeratorX * numeratorY));
2357 float8_regr_r2(PG_FUNCTION_ARGS)
2359 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2360 float8 *transvalues;
2371 transvalues = check_float8_array(transarray, "float8_regr_r2", 6);
2373 sumX = transvalues[1];
2374 sumX2 = transvalues[2];
2375 sumY = transvalues[3];
2376 sumY2 = transvalues[4];
2377 sumXY = transvalues[5];
2379 /* if N is 0 we should return NULL */
2383 numeratorX = N * sumX2 - sumX * sumX;
2384 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
2385 numeratorY = N * sumY2 - sumY * sumY;
2386 CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
2387 numeratorXY = N * sumXY - sumX * sumY;
2388 CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
2390 if (numeratorX <= 0)
2392 /* per spec, horizontal line produces 1.0 */
2393 if (numeratorY <= 0)
2394 PG_RETURN_FLOAT8(1.0);
2396 PG_RETURN_FLOAT8((numeratorXY * numeratorXY) /
2397 (numeratorX * numeratorY));
2401 float8_regr_slope(PG_FUNCTION_ARGS)
2403 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2404 float8 *transvalues;
2413 transvalues = check_float8_array(transarray, "float8_regr_slope", 6);
2415 sumX = transvalues[1];
2416 sumX2 = transvalues[2];
2417 sumY = transvalues[3];
2418 sumXY = transvalues[5];
2420 /* if N is 0 we should return NULL */
2424 numeratorX = N * sumX2 - sumX * sumX;
2425 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
2426 numeratorXY = N * sumXY - sumX * sumY;
2427 CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
2429 if (numeratorX <= 0)
2432 PG_RETURN_FLOAT8(numeratorXY / numeratorX);
2436 float8_regr_intercept(PG_FUNCTION_ARGS)
2438 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2439 float8 *transvalues;
2448 transvalues = check_float8_array(transarray, "float8_regr_intercept", 6);
2450 sumX = transvalues[1];
2451 sumX2 = transvalues[2];
2452 sumY = transvalues[3];
2453 sumXY = transvalues[5];
2455 /* if N is 0 we should return NULL */
2459 numeratorX = N * sumX2 - sumX * sumX;
2460 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
2461 numeratorXXY = sumY * sumX2 - sumX * sumXY;
2462 CHECKFLOATVAL(numeratorXXY, isinf(sumY) || isinf(sumX2) ||
2463 isinf(sumX) || isinf(sumXY), true);
2464 if (numeratorX <= 0)
2467 PG_RETURN_FLOAT8(numeratorXXY / numeratorX);
2472 * ====================================
2473 * MIXED-PRECISION ARITHMETIC OPERATORS
2474 * ====================================
2478 * float48pl - returns arg1 + arg2
2479 * float48mi - returns arg1 - arg2
2480 * float48mul - returns arg1 * arg2
2481 * float48div - returns arg1 / arg2
2484 float48pl(PG_FUNCTION_ARGS)
2486 float4 arg1 = PG_GETARG_FLOAT4(0);
2487 float8 arg2 = PG_GETARG_FLOAT8(1);
2490 result = arg1 + arg2;
2491 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
2492 PG_RETURN_FLOAT8(result);
2496 float48mi(PG_FUNCTION_ARGS)
2498 float4 arg1 = PG_GETARG_FLOAT4(0);
2499 float8 arg2 = PG_GETARG_FLOAT8(1);
2502 result = arg1 - arg2;
2503 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
2504 PG_RETURN_FLOAT8(result);
2508 float48mul(PG_FUNCTION_ARGS)
2510 float4 arg1 = PG_GETARG_FLOAT4(0);
2511 float8 arg2 = PG_GETARG_FLOAT8(1);
2514 result = arg1 * arg2;
2515 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
2516 arg1 == 0 || arg2 == 0);
2517 PG_RETURN_FLOAT8(result);
2521 float48div(PG_FUNCTION_ARGS)
2523 float4 arg1 = PG_GETARG_FLOAT4(0);
2524 float8 arg2 = PG_GETARG_FLOAT8(1);
2529 (errcode(ERRCODE_DIVISION_BY_ZERO),
2530 errmsg("division by zero")));
2532 result = arg1 / arg2;
2533 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
2534 PG_RETURN_FLOAT8(result);
2538 * float84pl - returns arg1 + arg2
2539 * float84mi - returns arg1 - arg2
2540 * float84mul - returns arg1 * arg2
2541 * float84div - returns arg1 / arg2
2544 float84pl(PG_FUNCTION_ARGS)
2546 float8 arg1 = PG_GETARG_FLOAT8(0);
2547 float4 arg2 = PG_GETARG_FLOAT4(1);
2550 result = arg1 + arg2;
2552 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
2553 PG_RETURN_FLOAT8(result);
2557 float84mi(PG_FUNCTION_ARGS)
2559 float8 arg1 = PG_GETARG_FLOAT8(0);
2560 float4 arg2 = PG_GETARG_FLOAT4(1);
2563 result = arg1 - arg2;
2565 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
2566 PG_RETURN_FLOAT8(result);
2570 float84mul(PG_FUNCTION_ARGS)
2572 float8 arg1 = PG_GETARG_FLOAT8(0);
2573 float4 arg2 = PG_GETARG_FLOAT4(1);
2576 result = arg1 * arg2;
2578 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
2579 arg1 == 0 || arg2 == 0);
2580 PG_RETURN_FLOAT8(result);
2584 float84div(PG_FUNCTION_ARGS)
2586 float8 arg1 = PG_GETARG_FLOAT8(0);
2587 float4 arg2 = PG_GETARG_FLOAT4(1);
2592 (errcode(ERRCODE_DIVISION_BY_ZERO),
2593 errmsg("division by zero")));
2595 result = arg1 / arg2;
2597 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
2598 PG_RETURN_FLOAT8(result);
2602 * ====================
2603 * COMPARISON OPERATORS
2604 * ====================
2608 * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
2611 float48eq(PG_FUNCTION_ARGS)
2613 float4 arg1 = PG_GETARG_FLOAT4(0);
2614 float8 arg2 = PG_GETARG_FLOAT8(1);
2616 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
2620 float48ne(PG_FUNCTION_ARGS)
2622 float4 arg1 = PG_GETARG_FLOAT4(0);
2623 float8 arg2 = PG_GETARG_FLOAT8(1);
2625 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
2629 float48lt(PG_FUNCTION_ARGS)
2631 float4 arg1 = PG_GETARG_FLOAT4(0);
2632 float8 arg2 = PG_GETARG_FLOAT8(1);
2634 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
2638 float48le(PG_FUNCTION_ARGS)
2640 float4 arg1 = PG_GETARG_FLOAT4(0);
2641 float8 arg2 = PG_GETARG_FLOAT8(1);
2643 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
2647 float48gt(PG_FUNCTION_ARGS)
2649 float4 arg1 = PG_GETARG_FLOAT4(0);
2650 float8 arg2 = PG_GETARG_FLOAT8(1);
2652 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
2656 float48ge(PG_FUNCTION_ARGS)
2658 float4 arg1 = PG_GETARG_FLOAT4(0);
2659 float8 arg2 = PG_GETARG_FLOAT8(1);
2661 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
2665 * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
2668 float84eq(PG_FUNCTION_ARGS)
2670 float8 arg1 = PG_GETARG_FLOAT8(0);
2671 float4 arg2 = PG_GETARG_FLOAT4(1);
2673 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
2677 float84ne(PG_FUNCTION_ARGS)
2679 float8 arg1 = PG_GETARG_FLOAT8(0);
2680 float4 arg2 = PG_GETARG_FLOAT4(1);
2682 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
2686 float84lt(PG_FUNCTION_ARGS)
2688 float8 arg1 = PG_GETARG_FLOAT8(0);
2689 float4 arg2 = PG_GETARG_FLOAT4(1);
2691 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
2695 float84le(PG_FUNCTION_ARGS)
2697 float8 arg1 = PG_GETARG_FLOAT8(0);
2698 float4 arg2 = PG_GETARG_FLOAT4(1);
2700 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
2704 float84gt(PG_FUNCTION_ARGS)
2706 float8 arg1 = PG_GETARG_FLOAT8(0);
2707 float4 arg2 = PG_GETARG_FLOAT4(1);
2709 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
2713 float84ge(PG_FUNCTION_ARGS)
2715 float8 arg1 = PG_GETARG_FLOAT8(0);
2716 float4 arg2 = PG_GETARG_FLOAT4(1);
2718 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
2722 * Implements the float8 version of the width_bucket() function
2723 * defined by SQL2003. See also width_bucket_numeric().
2725 * 'bound1' and 'bound2' are the lower and upper bounds of the
2726 * histogram's range, respectively. 'count' is the number of buckets
2727 * in the histogram. width_bucket() returns an integer indicating the
2728 * bucket number that 'operand' belongs to in an equiwidth histogram
2729 * with the specified characteristics. An operand smaller than the
2730 * lower bound is assigned to bucket 0. An operand greater than the
2731 * upper bound is assigned to an additional bucket (with number
2732 * count+1). We don't allow "NaN" for any of the float8 inputs, and we
2733 * don't allow either of the histogram bounds to be +/- infinity.
2736 width_bucket_float8(PG_FUNCTION_ARGS)
2738 float8 operand = PG_GETARG_FLOAT8(0);
2739 float8 bound1 = PG_GETARG_FLOAT8(1);
2740 float8 bound2 = PG_GETARG_FLOAT8(2);
2741 int32 count = PG_GETARG_INT32(3);
2746 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
2747 errmsg("count must be greater than zero")));
2749 if (isnan(operand) || isnan(bound1) || isnan(bound2))
2751 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
2752 errmsg("operand, lower bound, and upper bound cannot be NaN")));
2754 /* Note that we allow "operand" to be infinite */
2755 if (isinf(bound1) || isinf(bound2))
2757 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
2758 errmsg("lower and upper bounds must be finite")));
2760 if (bound1 < bound2)
2762 if (operand < bound1)
2764 else if (operand >= bound2)
2767 /* check for overflow */
2770 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2771 errmsg("integer out of range")));
2774 result = ((float8) count * (operand - bound1) / (bound2 - bound1)) + 1;
2776 else if (bound1 > bound2)
2778 if (operand > bound1)
2780 else if (operand <= bound2)
2783 /* check for overflow */
2786 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2787 errmsg("integer out of range")));
2790 result = ((float8) count * (bound1 - operand) / (bound1 - bound2)) + 1;
2795 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
2796 errmsg("lower bound cannot equal upper bound")));
2797 result = 0; /* keep the compiler quiet */
2800 PG_RETURN_INT32(result);
2803 /* ========== PRIVATE ROUTINES ========== */
2810 int isneg = (x < 0.0);
2811 double absx = fabs(x);
2812 double tmpres = pow(absx, (double) 1.0 / (double) 3.0);
2815 * The result is somewhat inaccurate --- not really pow()'s fault, as the
2816 * exponent it's handed contains roundoff error. We can improve the
2817 * accuracy by doing one iteration of Newton's formula. Beware of zero
2821 tmpres -= (tmpres - absx / (tmpres * tmpres)) / (double) 3.0;
2823 return isneg ? -tmpres : tmpres;
2826 #endif /* !HAVE_CBRT */