PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
float.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * float.c
4 * Functions for the built-in floating-point types.
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/float.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include <ctype.h>
18#include <float.h>
19#include <math.h>
20#include <limits.h>
21
22#include "catalog/pg_type.h"
23#include "common/int.h"
24#include "common/shortest_dec.h"
25#include "libpq/pqformat.h"
26#include "utils/array.h"
27#include "utils/float.h"
28#include "utils/fmgrprotos.h"
29#include "utils/sortsupport.h"
30
31
32/*
33 * Configurable GUC parameter
34 *
35 * If >0, use shortest-decimal format for output; this is both the default and
36 * allows for compatibility with clients that explicitly set a value here to
37 * get round-trip-accurate results. If 0 or less, then use the old, slow,
38 * decimal rounding method.
39 */
41
42/* Cached constants for degree-based trig functions */
43static bool degree_consts_set = false;
44static float8 sin_30 = 0;
46static float8 asin_0_5 = 0;
47static float8 acos_0_5 = 0;
48static float8 atan_1_0 = 0;
49static float8 tan_45 = 0;
50static float8 cot_45 = 0;
51
52/*
53 * These are intentionally not static; don't "fix" them. They will never
54 * be referenced by other files, much less changed; but we don't want the
55 * compiler to know that, else it might try to precompute expressions
56 * involving them. See comments for init_degree_constants().
57 *
58 * The additional extern declarations are to silence
59 * -Wmissing-variable-declarations.
60 */
65extern float8 degree_c_one;
71
72/* Local function prototypes */
73static double sind_q1(double x);
74static double cosd_q1(double x);
75static void init_degree_constants(void);
76
77
78/*
79 * We use these out-of-line ereport() calls to report float overflow,
80 * underflow, and zero-divide, because following our usual practice of
81 * repeating them at each call site would lead to a lot of code bloat.
82 *
83 * This does mean that you don't get a useful error location indicator.
84 */
85pg_noinline void
87{
89 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
90 errmsg("value out of range: overflow")));
91}
92
93pg_noinline void
95{
97 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
98 errmsg("value out of range: underflow")));
99}
100
101pg_noinline void
103{
105 (errcode(ERRCODE_DIVISION_BY_ZERO),
106 errmsg("division by zero")));
107}
108
109
110/*
111 * Returns -1 if 'val' represents negative infinity, 1 if 'val'
112 * represents (positive) infinity, and 0 otherwise. On some platforms,
113 * this is equivalent to the isinf() macro, but not everywhere: C99
114 * does not specify that isinf() needs to distinguish between positive
115 * and negative infinity.
116 */
117int
119{
120 int inf = isinf(val);
121
122 if (inf == 0)
123 return 0;
124 else if (val > 0)
125 return 1;
126 else
127 return -1;
128}
129
130
131/* ========== USER I/O ROUTINES ========== */
132
133
134/*
135 * float4in - converts "num" to float4
136 *
137 * Note that this code now uses strtof(), where it used to use strtod().
138 *
139 * The motivation for using strtof() is to avoid a double-rounding problem:
140 * for certain decimal inputs, if you round the input correctly to a double,
141 * and then round the double to a float, the result is incorrect in that it
142 * does not match the result of rounding the decimal value to float directly.
143 *
144 * One of the best examples is 7.038531e-26:
145 *
146 * 0xAE43FDp-107 = 7.03853069185120912085...e-26
147 * midpoint 7.03853100000000022281...e-26
148 * 0xAE43FEp-107 = 7.03853130814879132477...e-26
149 *
150 * making 0xAE43FDp-107 the correct float result, but if you do the conversion
151 * via a double, you get
152 *
153 * 0xAE43FD.7FFFFFF8p-107 = 7.03853099999999907487...e-26
154 * midpoint 7.03853099999999964884...e-26
155 * 0xAE43FD.80000000p-107 = 7.03853100000000022281...e-26
156 * 0xAE43FD.80000008p-107 = 7.03853100000000137076...e-26
157 *
158 * so the value rounds to the double exactly on the midpoint between the two
159 * nearest floats, and then rounding again to a float gives the incorrect
160 * result of 0xAE43FEp-107.
161 *
162 */
163Datum
165{
166 char *num = PG_GETARG_CSTRING(0);
167
168 PG_RETURN_FLOAT4(float4in_internal(num, NULL, "real", num,
169 fcinfo->context));
170}
171
172/*
173 * float4in_internal - guts of float4in()
174 *
175 * This is exposed for use by functions that want a reasonably
176 * platform-independent way of inputting floats. The behavior is
177 * essentially like strtof + ereturn on error.
178 *
179 * Uses the same API as float8in_internal below, so most of its
180 * comments also apply here, except regarding use in geometric types.
181 */
182float4
183float4in_internal(char *num, char **endptr_p,
184 const char *type_name, const char *orig_string,
185 struct Node *escontext)
186{
187 float val;
188 char *endptr;
189
190 /*
191 * endptr points to the first character _after_ the sequence we recognized
192 * as a valid floating point number. orig_string points to the original
193 * input string.
194 */
195
196 /* skip leading whitespace */
197 while (*num != '\0' && isspace((unsigned char) *num))
198 num++;
199
200 /*
201 * Check for an empty-string input to begin with, to avoid the vagaries of
202 * strtod() on different platforms.
203 */
204 if (*num == '\0')
205 ereturn(escontext, 0,
206 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
207 errmsg("invalid input syntax for type %s: \"%s\"",
208 type_name, orig_string)));
209
210 errno = 0;
211 val = strtof(num, &endptr);
212
213 /* did we not see anything that looks like a double? */
214 if (endptr == num || errno != 0)
215 {
216 int save_errno = errno;
217
218 /*
219 * C99 requires that strtof() accept NaN, [+-]Infinity, and [+-]Inf,
220 * but not all platforms support all of these (and some accept them
221 * but set ERANGE anyway...) Therefore, we check for these inputs
222 * ourselves if strtof() fails.
223 *
224 * Note: C99 also requires hexadecimal input as well as some extended
225 * forms of NaN, but we consider these forms unportable and don't try
226 * to support them. You can use 'em if your strtof() takes 'em.
227 */
228 if (pg_strncasecmp(num, "NaN", 3) == 0)
229 {
231 endptr = num + 3;
232 }
233 else if (pg_strncasecmp(num, "Infinity", 8) == 0)
234 {
236 endptr = num + 8;
237 }
238 else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
239 {
241 endptr = num + 9;
242 }
243 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
244 {
246 endptr = num + 9;
247 }
248 else if (pg_strncasecmp(num, "inf", 3) == 0)
249 {
251 endptr = num + 3;
252 }
253 else if (pg_strncasecmp(num, "+inf", 4) == 0)
254 {
256 endptr = num + 4;
257 }
258 else if (pg_strncasecmp(num, "-inf", 4) == 0)
259 {
261 endptr = num + 4;
262 }
263 else if (save_errno == ERANGE)
264 {
265 /*
266 * Some platforms return ERANGE for denormalized numbers (those
267 * that are not zero, but are too close to zero to have full
268 * precision). We'd prefer not to throw error for that, so try to
269 * detect whether it's a "real" out-of-range condition by checking
270 * to see if the result is zero or huge.
271 */
272 if (val == 0.0 ||
273#if !defined(HUGE_VALF)
274 isinf(val)
275#else
276 (val >= HUGE_VALF || val <= -HUGE_VALF)
277#endif
278 )
279 {
280 /* see comments in float8in_internal for rationale */
281 char *errnumber = pstrdup(num);
282
283 errnumber[endptr - num] = '\0';
284
285 ereturn(escontext, 0,
286 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
287 errmsg("\"%s\" is out of range for type real",
288 errnumber)));
289 }
290 }
291 else
292 ereturn(escontext, 0,
293 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
294 errmsg("invalid input syntax for type %s: \"%s\"",
295 type_name, orig_string)));
296 }
297
298 /* skip trailing whitespace */
299 while (*endptr != '\0' && isspace((unsigned char) *endptr))
300 endptr++;
301
302 /* report stopping point if wanted, else complain if not end of string */
303 if (endptr_p)
304 *endptr_p = endptr;
305 else if (*endptr != '\0')
306 ereturn(escontext, 0,
307 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
308 errmsg("invalid input syntax for type %s: \"%s\"",
309 type_name, orig_string)));
310
311 return val;
312}
313
314/*
315 * float4out - converts a float4 number to a string
316 * using a standard output format
317 */
318Datum
320{
321 float4 num = PG_GETARG_FLOAT4(0);
322 char *ascii = (char *) palloc(32);
323 int ndig = FLT_DIG + extra_float_digits;
324
325 if (extra_float_digits > 0)
326 {
329 }
330
331 (void) pg_strfromd(ascii, 32, ndig, num);
333}
334
335/*
336 * float4recv - converts external binary format to float4
337 */
338Datum
340{
342
344}
345
346/*
347 * float4send - converts float4 to binary format
348 */
349Datum
351{
352 float4 num = PG_GETARG_FLOAT4(0);
354
356 pq_sendfloat4(&buf, num);
358}
359
360/*
361 * float8in - converts "num" to float8
362 */
363Datum
365{
366 char *num = PG_GETARG_CSTRING(0);
367
368 PG_RETURN_FLOAT8(float8in_internal(num, NULL, "double precision", num,
369 fcinfo->context));
370}
371
372/*
373 * float8in_internal - guts of float8in()
374 *
375 * This is exposed for use by functions that want a reasonably
376 * platform-independent way of inputting doubles. The behavior is
377 * essentially like strtod + ereturn on error, but note the following
378 * differences:
379 * 1. Both leading and trailing whitespace are skipped.
380 * 2. If endptr_p is NULL, we report error if there's trailing junk.
381 * Otherwise, it's up to the caller to complain about trailing junk.
382 * 3. In event of a syntax error, the report mentions the given type_name
383 * and prints orig_string as the input; this is meant to support use of
384 * this function with types such as "box" and "point", where what we are
385 * parsing here is just a substring of orig_string.
386 *
387 * If escontext points to an ErrorSaveContext node, that is filled instead
388 * of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
389 * to detect errors.
390 *
391 * "num" could validly be declared "const char *", but that results in an
392 * unreasonable amount of extra casting both here and in callers, so we don't.
393 */
394float8
395float8in_internal(char *num, char **endptr_p,
396 const char *type_name, const char *orig_string,
397 struct Node *escontext)
398{
399 double val;
400 char *endptr;
401
402 /* skip leading whitespace */
403 while (*num != '\0' && isspace((unsigned char) *num))
404 num++;
405
406 /*
407 * Check for an empty-string input to begin with, to avoid the vagaries of
408 * strtod() on different platforms.
409 */
410 if (*num == '\0')
411 ereturn(escontext, 0,
412 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
413 errmsg("invalid input syntax for type %s: \"%s\"",
414 type_name, orig_string)));
415
416 errno = 0;
417 val = strtod(num, &endptr);
418
419 /* did we not see anything that looks like a double? */
420 if (endptr == num || errno != 0)
421 {
422 int save_errno = errno;
423
424 /*
425 * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
426 * but not all platforms support all of these (and some accept them
427 * but set ERANGE anyway...) Therefore, we check for these inputs
428 * ourselves if strtod() fails.
429 *
430 * Note: C99 also requires hexadecimal input as well as some extended
431 * forms of NaN, but we consider these forms unportable and don't try
432 * to support them. You can use 'em if your strtod() takes 'em.
433 */
434 if (pg_strncasecmp(num, "NaN", 3) == 0)
435 {
437 endptr = num + 3;
438 }
439 else if (pg_strncasecmp(num, "Infinity", 8) == 0)
440 {
442 endptr = num + 8;
443 }
444 else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
445 {
447 endptr = num + 9;
448 }
449 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
450 {
452 endptr = num + 9;
453 }
454 else if (pg_strncasecmp(num, "inf", 3) == 0)
455 {
457 endptr = num + 3;
458 }
459 else if (pg_strncasecmp(num, "+inf", 4) == 0)
460 {
462 endptr = num + 4;
463 }
464 else if (pg_strncasecmp(num, "-inf", 4) == 0)
465 {
467 endptr = num + 4;
468 }
469 else if (save_errno == ERANGE)
470 {
471 /*
472 * Some platforms return ERANGE for denormalized numbers (those
473 * that are not zero, but are too close to zero to have full
474 * precision). We'd prefer not to throw error for that, so try to
475 * detect whether it's a "real" out-of-range condition by checking
476 * to see if the result is zero or huge.
477 *
478 * On error, we intentionally complain about double precision not
479 * the given type name, and we print only the part of the string
480 * that is the current number.
481 */
482 if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
483 {
484 char *errnumber = pstrdup(num);
485
486 errnumber[endptr - num] = '\0';
487 ereturn(escontext, 0,
488 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
489 errmsg("\"%s\" is out of range for type double precision",
490 errnumber)));
491 }
492 }
493 else
494 ereturn(escontext, 0,
495 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
496 errmsg("invalid input syntax for type %s: \"%s\"",
497 type_name, orig_string)));
498 }
499
500 /* skip trailing whitespace */
501 while (*endptr != '\0' && isspace((unsigned char) *endptr))
502 endptr++;
503
504 /* report stopping point if wanted, else complain if not end of string */
505 if (endptr_p)
506 *endptr_p = endptr;
507 else if (*endptr != '\0')
508 ereturn(escontext, 0,
509 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
510 errmsg("invalid input syntax for type %s: \"%s\"",
511 type_name, orig_string)));
512
513 return val;
514}
515
516
517/*
518 * float8out - converts float8 number to a string
519 * using a standard output format
520 */
521Datum
523{
524 float8 num = PG_GETARG_FLOAT8(0);
525
527}
528
529/*
530 * float8out_internal - guts of float8out()
531 *
532 * This is exposed for use by functions that want a reasonably
533 * platform-independent way of outputting doubles.
534 * The result is always palloc'd.
535 */
536char *
538{
539 char *ascii = (char *) palloc(32);
540 int ndig = DBL_DIG + extra_float_digits;
541
542 if (extra_float_digits > 0)
543 {
545 return ascii;
546 }
547
548 (void) pg_strfromd(ascii, 32, ndig, num);
549 return ascii;
550}
551
552/*
553 * float8recv - converts external binary format to float8
554 */
555Datum
557{
559
561}
562
563/*
564 * float8send - converts float8 to binary format
565 */
566Datum
568{
569 float8 num = PG_GETARG_FLOAT8(0);
571
573 pq_sendfloat8(&buf, num);
575}
576
577
578/* ========== PUBLIC ROUTINES ========== */
579
580
581/*
582 * ======================
583 * FLOAT4 BASE OPERATIONS
584 * ======================
585 */
586
587/*
588 * float4abs - returns |arg1| (absolute value)
589 */
590Datum
592{
593 float4 arg1 = PG_GETARG_FLOAT4(0);
594
595 PG_RETURN_FLOAT4(fabsf(arg1));
596}
597
598/*
599 * float4um - returns -arg1 (unary minus)
600 */
601Datum
603{
604 float4 arg1 = PG_GETARG_FLOAT4(0);
605 float4 result;
606
607 result = -arg1;
608 PG_RETURN_FLOAT4(result);
609}
610
611Datum
613{
615
617}
618
619Datum
621{
622 float4 arg1 = PG_GETARG_FLOAT4(0);
623 float4 arg2 = PG_GETARG_FLOAT4(1);
624 float4 result;
625
626 if (float4_gt(arg1, arg2))
627 result = arg1;
628 else
629 result = arg2;
630 PG_RETURN_FLOAT4(result);
631}
632
633Datum
635{
636 float4 arg1 = PG_GETARG_FLOAT4(0);
637 float4 arg2 = PG_GETARG_FLOAT4(1);
638 float4 result;
639
640 if (float4_lt(arg1, arg2))
641 result = arg1;
642 else
643 result = arg2;
644 PG_RETURN_FLOAT4(result);
645}
646
647/*
648 * ======================
649 * FLOAT8 BASE OPERATIONS
650 * ======================
651 */
652
653/*
654 * float8abs - returns |arg1| (absolute value)
655 */
656Datum
658{
659 float8 arg1 = PG_GETARG_FLOAT8(0);
660
661 PG_RETURN_FLOAT8(fabs(arg1));
662}
663
664
665/*
666 * float8um - returns -arg1 (unary minus)
667 */
668Datum
670{
671 float8 arg1 = PG_GETARG_FLOAT8(0);
672 float8 result;
673
674 result = -arg1;
675 PG_RETURN_FLOAT8(result);
676}
677
678Datum
680{
682
684}
685
686Datum
688{
689 float8 arg1 = PG_GETARG_FLOAT8(0);
690 float8 arg2 = PG_GETARG_FLOAT8(1);
691 float8 result;
692
693 if (float8_gt(arg1, arg2))
694 result = arg1;
695 else
696 result = arg2;
697 PG_RETURN_FLOAT8(result);
698}
699
700Datum
702{
703 float8 arg1 = PG_GETARG_FLOAT8(0);
704 float8 arg2 = PG_GETARG_FLOAT8(1);
705 float8 result;
706
707 if (float8_lt(arg1, arg2))
708 result = arg1;
709 else
710 result = arg2;
711 PG_RETURN_FLOAT8(result);
712}
713
714
715/*
716 * ====================
717 * ARITHMETIC OPERATORS
718 * ====================
719 */
720
721/*
722 * float4pl - returns arg1 + arg2
723 * float4mi - returns arg1 - arg2
724 * float4mul - returns arg1 * arg2
725 * float4div - returns arg1 / arg2
726 */
727Datum
729{
730 float4 arg1 = PG_GETARG_FLOAT4(0);
731 float4 arg2 = PG_GETARG_FLOAT4(1);
732
733 PG_RETURN_FLOAT4(float4_pl(arg1, arg2));
734}
735
736Datum
738{
739 float4 arg1 = PG_GETARG_FLOAT4(0);
740 float4 arg2 = PG_GETARG_FLOAT4(1);
741
742 PG_RETURN_FLOAT4(float4_mi(arg1, arg2));
743}
744
745Datum
747{
748 float4 arg1 = PG_GETARG_FLOAT4(0);
749 float4 arg2 = PG_GETARG_FLOAT4(1);
750
751 PG_RETURN_FLOAT4(float4_mul(arg1, arg2));
752}
753
754Datum
756{
757 float4 arg1 = PG_GETARG_FLOAT4(0);
758 float4 arg2 = PG_GETARG_FLOAT4(1);
759
760 PG_RETURN_FLOAT4(float4_div(arg1, arg2));
761}
762
763/*
764 * float8pl - returns arg1 + arg2
765 * float8mi - returns arg1 - arg2
766 * float8mul - returns arg1 * arg2
767 * float8div - returns arg1 / arg2
768 */
769Datum
771{
772 float8 arg1 = PG_GETARG_FLOAT8(0);
773 float8 arg2 = PG_GETARG_FLOAT8(1);
774
775 PG_RETURN_FLOAT8(float8_pl(arg1, arg2));
776}
777
778Datum
780{
781 float8 arg1 = PG_GETARG_FLOAT8(0);
782 float8 arg2 = PG_GETARG_FLOAT8(1);
783
784 PG_RETURN_FLOAT8(float8_mi(arg1, arg2));
785}
786
787Datum
789{
790 float8 arg1 = PG_GETARG_FLOAT8(0);
791 float8 arg2 = PG_GETARG_FLOAT8(1);
792
793 PG_RETURN_FLOAT8(float8_mul(arg1, arg2));
794}
795
796Datum
798{
799 float8 arg1 = PG_GETARG_FLOAT8(0);
800 float8 arg2 = PG_GETARG_FLOAT8(1);
801
802 PG_RETURN_FLOAT8(float8_div(arg1, arg2));
803}
804
805
806/*
807 * ====================
808 * COMPARISON OPERATORS
809 * ====================
810 */
811
812/*
813 * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
814 */
815int
817{
818 if (float4_gt(a, b))
819 return 1;
820 if (float4_lt(a, b))
821 return -1;
822 return 0;
823}
824
825Datum
827{
828 float4 arg1 = PG_GETARG_FLOAT4(0);
829 float4 arg2 = PG_GETARG_FLOAT4(1);
830
831 PG_RETURN_BOOL(float4_eq(arg1, arg2));
832}
833
834Datum
836{
837 float4 arg1 = PG_GETARG_FLOAT4(0);
838 float4 arg2 = PG_GETARG_FLOAT4(1);
839
840 PG_RETURN_BOOL(float4_ne(arg1, arg2));
841}
842
843Datum
845{
846 float4 arg1 = PG_GETARG_FLOAT4(0);
847 float4 arg2 = PG_GETARG_FLOAT4(1);
848
849 PG_RETURN_BOOL(float4_lt(arg1, arg2));
850}
851
852Datum
854{
855 float4 arg1 = PG_GETARG_FLOAT4(0);
856 float4 arg2 = PG_GETARG_FLOAT4(1);
857
858 PG_RETURN_BOOL(float4_le(arg1, arg2));
859}
860
861Datum
863{
864 float4 arg1 = PG_GETARG_FLOAT4(0);
865 float4 arg2 = PG_GETARG_FLOAT4(1);
866
867 PG_RETURN_BOOL(float4_gt(arg1, arg2));
868}
869
870Datum
872{
873 float4 arg1 = PG_GETARG_FLOAT4(0);
874 float4 arg2 = PG_GETARG_FLOAT4(1);
875
876 PG_RETURN_BOOL(float4_ge(arg1, arg2));
877}
878
879Datum
881{
882 float4 arg1 = PG_GETARG_FLOAT4(0);
883 float4 arg2 = PG_GETARG_FLOAT4(1);
884
886}
887
888static int
890{
891 float4 arg1 = DatumGetFloat4(x);
892 float4 arg2 = DatumGetFloat4(y);
893
894 return float4_cmp_internal(arg1, arg2);
895}
896
897Datum
899{
901
904}
905
906/*
907 * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
908 */
909int
911{
912 if (float8_gt(a, b))
913 return 1;
914 if (float8_lt(a, b))
915 return -1;
916 return 0;
917}
918
919Datum
921{
922 float8 arg1 = PG_GETARG_FLOAT8(0);
923 float8 arg2 = PG_GETARG_FLOAT8(1);
924
925 PG_RETURN_BOOL(float8_eq(arg1, arg2));
926}
927
928Datum
930{
931 float8 arg1 = PG_GETARG_FLOAT8(0);
932 float8 arg2 = PG_GETARG_FLOAT8(1);
933
934 PG_RETURN_BOOL(float8_ne(arg1, arg2));
935}
936
937Datum
939{
940 float8 arg1 = PG_GETARG_FLOAT8(0);
941 float8 arg2 = PG_GETARG_FLOAT8(1);
942
943 PG_RETURN_BOOL(float8_lt(arg1, arg2));
944}
945
946Datum
948{
949 float8 arg1 = PG_GETARG_FLOAT8(0);
950 float8 arg2 = PG_GETARG_FLOAT8(1);
951
952 PG_RETURN_BOOL(float8_le(arg1, arg2));
953}
954
955Datum
957{
958 float8 arg1 = PG_GETARG_FLOAT8(0);
959 float8 arg2 = PG_GETARG_FLOAT8(1);
960
961 PG_RETURN_BOOL(float8_gt(arg1, arg2));
962}
963
964Datum
966{
967 float8 arg1 = PG_GETARG_FLOAT8(0);
968 float8 arg2 = PG_GETARG_FLOAT8(1);
969
970 PG_RETURN_BOOL(float8_ge(arg1, arg2));
971}
972
973Datum
975{
976 float8 arg1 = PG_GETARG_FLOAT8(0);
977 float8 arg2 = PG_GETARG_FLOAT8(1);
978
980}
981
982static int
984{
985 float8 arg1 = DatumGetFloat8(x);
986 float8 arg2 = DatumGetFloat8(y);
987
988 return float8_cmp_internal(arg1, arg2);
989}
990
991Datum
993{
995
998}
999
1000Datum
1002{
1003 float4 arg1 = PG_GETARG_FLOAT4(0);
1004 float8 arg2 = PG_GETARG_FLOAT8(1);
1005
1006 /* widen float4 to float8 and then compare */
1008}
1009
1010Datum
1012{
1013 float8 arg1 = PG_GETARG_FLOAT8(0);
1014 float4 arg2 = PG_GETARG_FLOAT4(1);
1015
1016 /* widen float4 to float8 and then compare */
1018}
1019
1020/*
1021 * in_range support function for float8.
1022 *
1023 * Note: we needn't supply a float8_float4 variant, as implicit coercion
1024 * of the offset value takes care of that scenario just as well.
1025 */
1026Datum
1028{
1030 float8 base = PG_GETARG_FLOAT8(1);
1031 float8 offset = PG_GETARG_FLOAT8(2);
1032 bool sub = PG_GETARG_BOOL(3);
1033 bool less = PG_GETARG_BOOL(4);
1034 float8 sum;
1035
1036 /*
1037 * Reject negative or NaN offset. Negative is per spec, and NaN is
1038 * because appropriate semantics for that seem non-obvious.
1039 */
1040 if (isnan(offset) || offset < 0)
1041 ereport(ERROR,
1042 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
1043 errmsg("invalid preceding or following size in window function")));
1044
1045 /*
1046 * Deal with cases where val and/or base is NaN, following the rule that
1047 * NaN sorts after non-NaN (cf float8_cmp_internal). The offset cannot
1048 * affect the conclusion.
1049 */
1050 if (isnan(val))
1051 {
1052 if (isnan(base))
1053 PG_RETURN_BOOL(true); /* NAN = NAN */
1054 else
1055 PG_RETURN_BOOL(!less); /* NAN > non-NAN */
1056 }
1057 else if (isnan(base))
1058 {
1059 PG_RETURN_BOOL(less); /* non-NAN < NAN */
1060 }
1061
1062 /*
1063 * Deal with cases where both base and offset are infinite, and computing
1064 * base +/- offset would produce NaN. This corresponds to a window frame
1065 * whose boundary infinitely precedes +inf or infinitely follows -inf,
1066 * which is not well-defined. For consistency with other cases involving
1067 * infinities, such as the fact that +inf infinitely follows +inf, we
1068 * choose to assume that +inf infinitely precedes +inf and -inf infinitely
1069 * follows -inf, and therefore that all finite and infinite values are in
1070 * such a window frame.
1071 *
1072 * offset is known positive, so we need only check the sign of base in
1073 * this test.
1074 */
1075 if (isinf(offset) && isinf(base) &&
1076 (sub ? base > 0 : base < 0))
1077 PG_RETURN_BOOL(true);
1078
1079 /*
1080 * Otherwise it should be safe to compute base +/- offset. We trust the
1081 * FPU to cope if an input is +/-inf or the true sum would overflow, and
1082 * produce a suitably signed infinity, which will compare properly against
1083 * val whether or not that's infinity.
1084 */
1085 if (sub)
1086 sum = base - offset;
1087 else
1088 sum = base + offset;
1089
1090 if (less)
1091 PG_RETURN_BOOL(val <= sum);
1092 else
1093 PG_RETURN_BOOL(val >= sum);
1094}
1095
1096/*
1097 * in_range support function for float4.
1098 *
1099 * We would need a float4_float8 variant in any case, so we supply that and
1100 * let implicit coercion take care of the float4_float4 case.
1101 */
1102Datum
1104{
1106 float4 base = PG_GETARG_FLOAT4(1);
1107 float8 offset = PG_GETARG_FLOAT8(2);
1108 bool sub = PG_GETARG_BOOL(3);
1109 bool less = PG_GETARG_BOOL(4);
1110 float8 sum;
1111
1112 /*
1113 * Reject negative or NaN offset. Negative is per spec, and NaN is
1114 * because appropriate semantics for that seem non-obvious.
1115 */
1116 if (isnan(offset) || offset < 0)
1117 ereport(ERROR,
1118 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
1119 errmsg("invalid preceding or following size in window function")));
1120
1121 /*
1122 * Deal with cases where val and/or base is NaN, following the rule that
1123 * NaN sorts after non-NaN (cf float8_cmp_internal). The offset cannot
1124 * affect the conclusion.
1125 */
1126 if (isnan(val))
1127 {
1128 if (isnan(base))
1129 PG_RETURN_BOOL(true); /* NAN = NAN */
1130 else
1131 PG_RETURN_BOOL(!less); /* NAN > non-NAN */
1132 }
1133 else if (isnan(base))
1134 {
1135 PG_RETURN_BOOL(less); /* non-NAN < NAN */
1136 }
1137
1138 /*
1139 * Deal with cases where both base and offset are infinite, and computing
1140 * base +/- offset would produce NaN. This corresponds to a window frame
1141 * whose boundary infinitely precedes +inf or infinitely follows -inf,
1142 * which is not well-defined. For consistency with other cases involving
1143 * infinities, such as the fact that +inf infinitely follows +inf, we
1144 * choose to assume that +inf infinitely precedes +inf and -inf infinitely
1145 * follows -inf, and therefore that all finite and infinite values are in
1146 * such a window frame.
1147 *
1148 * offset is known positive, so we need only check the sign of base in
1149 * this test.
1150 */
1151 if (isinf(offset) && isinf(base) &&
1152 (sub ? base > 0 : base < 0))
1153 PG_RETURN_BOOL(true);
1154
1155 /*
1156 * Otherwise it should be safe to compute base +/- offset. We trust the
1157 * FPU to cope if an input is +/-inf or the true sum would overflow, and
1158 * produce a suitably signed infinity, which will compare properly against
1159 * val whether or not that's infinity.
1160 */
1161 if (sub)
1162 sum = base - offset;
1163 else
1164 sum = base + offset;
1165
1166 if (less)
1167 PG_RETURN_BOOL(val <= sum);
1168 else
1169 PG_RETURN_BOOL(val >= sum);
1170}
1171
1172
1173/*
1174 * ===================
1175 * CONVERSION ROUTINES
1176 * ===================
1177 */
1178
1179/*
1180 * ftod - converts a float4 number to a float8 number
1181 */
1182Datum
1184{
1185 float4 num = PG_GETARG_FLOAT4(0);
1186
1187 PG_RETURN_FLOAT8((float8) num);
1188}
1189
1190
1191/*
1192 * dtof - converts a float8 number to a float4 number
1193 */
1194Datum
1196{
1197 float8 num = PG_GETARG_FLOAT8(0);
1198 float4 result;
1199
1200 result = (float4) num;
1201 if (unlikely(isinf(result)) && !isinf(num))
1203 if (unlikely(result == 0.0f) && num != 0.0)
1205
1206 PG_RETURN_FLOAT4(result);
1207}
1208
1209
1210/*
1211 * dtoi4 - converts a float8 number to an int4 number
1212 */
1213Datum
1215{
1216 float8 num = PG_GETARG_FLOAT8(0);
1217
1218 /*
1219 * Get rid of any fractional part in the input. This is so we don't fail
1220 * on just-out-of-range values that would round into range. Note
1221 * assumption that rint() will pass through a NaN or Inf unchanged.
1222 */
1223 num = rint(num);
1224
1225 /* Range check */
1226 if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT32(num)))
1227 ereport(ERROR,
1228 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1229 errmsg("integer out of range")));
1230
1231 PG_RETURN_INT32((int32) num);
1232}
1233
1234
1235/*
1236 * dtoi2 - converts a float8 number to an int2 number
1237 */
1238Datum
1240{
1241 float8 num = PG_GETARG_FLOAT8(0);
1242
1243 /*
1244 * Get rid of any fractional part in the input. This is so we don't fail
1245 * on just-out-of-range values that would round into range. Note
1246 * assumption that rint() will pass through a NaN or Inf unchanged.
1247 */
1248 num = rint(num);
1249
1250 /* Range check */
1251 if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT16(num)))
1252 ereport(ERROR,
1253 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1254 errmsg("smallint out of range")));
1255
1256 PG_RETURN_INT16((int16) num);
1257}
1258
1259
1260/*
1261 * i4tod - converts an int4 number to a float8 number
1262 */
1263Datum
1265{
1266 int32 num = PG_GETARG_INT32(0);
1267
1268 PG_RETURN_FLOAT8((float8) num);
1269}
1270
1271
1272/*
1273 * i2tod - converts an int2 number to a float8 number
1274 */
1275Datum
1277{
1278 int16 num = PG_GETARG_INT16(0);
1279
1280 PG_RETURN_FLOAT8((float8) num);
1281}
1282
1283
1284/*
1285 * ftoi4 - converts a float4 number to an int4 number
1286 */
1287Datum
1289{
1290 float4 num = PG_GETARG_FLOAT4(0);
1291
1292 /*
1293 * Get rid of any fractional part in the input. This is so we don't fail
1294 * on just-out-of-range values that would round into range. Note
1295 * assumption that rint() will pass through a NaN or Inf unchanged.
1296 */
1297 num = rint(num);
1298
1299 /* Range check */
1300 if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT32(num)))
1301 ereport(ERROR,
1302 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1303 errmsg("integer out of range")));
1304
1305 PG_RETURN_INT32((int32) num);
1306}
1307
1308
1309/*
1310 * ftoi2 - converts a float4 number to an int2 number
1311 */
1312Datum
1314{
1315 float4 num = PG_GETARG_FLOAT4(0);
1316
1317 /*
1318 * Get rid of any fractional part in the input. This is so we don't fail
1319 * on just-out-of-range values that would round into range. Note
1320 * assumption that rint() will pass through a NaN or Inf unchanged.
1321 */
1322 num = rint(num);
1323
1324 /* Range check */
1325 if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT16(num)))
1326 ereport(ERROR,
1327 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1328 errmsg("smallint out of range")));
1329
1330 PG_RETURN_INT16((int16) num);
1331}
1332
1333
1334/*
1335 * i4tof - converts an int4 number to a float4 number
1336 */
1337Datum
1339{
1340 int32 num = PG_GETARG_INT32(0);
1341
1342 PG_RETURN_FLOAT4((float4) num);
1343}
1344
1345
1346/*
1347 * i2tof - converts an int2 number to a float4 number
1348 */
1349Datum
1351{
1352 int16 num = PG_GETARG_INT16(0);
1353
1354 PG_RETURN_FLOAT4((float4) num);
1355}
1356
1357
1358/*
1359 * =======================
1360 * RANDOM FLOAT8 OPERATORS
1361 * =======================
1362 */
1363
1364/*
1365 * dround - returns ROUND(arg1)
1366 */
1367Datum
1369{
1370 float8 arg1 = PG_GETARG_FLOAT8(0);
1371
1372 PG_RETURN_FLOAT8(rint(arg1));
1373}
1374
1375/*
1376 * dceil - returns the smallest integer greater than or
1377 * equal to the specified float
1378 */
1379Datum
1381{
1382 float8 arg1 = PG_GETARG_FLOAT8(0);
1383
1384 PG_RETURN_FLOAT8(ceil(arg1));
1385}
1386
1387/*
1388 * dfloor - returns the largest integer lesser than or
1389 * equal to the specified float
1390 */
1391Datum
1393{
1394 float8 arg1 = PG_GETARG_FLOAT8(0);
1395
1396 PG_RETURN_FLOAT8(floor(arg1));
1397}
1398
1399/*
1400 * dsign - returns -1 if the argument is less than 0, 0
1401 * if the argument is equal to 0, and 1 if the
1402 * argument is greater than zero.
1403 */
1404Datum
1406{
1407 float8 arg1 = PG_GETARG_FLOAT8(0);
1408 float8 result;
1409
1410 if (arg1 > 0)
1411 result = 1.0;
1412 else if (arg1 < 0)
1413 result = -1.0;
1414 else
1415 result = 0.0;
1416
1417 PG_RETURN_FLOAT8(result);
1418}
1419
1420/*
1421 * dtrunc - returns truncation-towards-zero of arg1,
1422 * arg1 >= 0 ... the greatest integer less
1423 * than or equal to arg1
1424 * arg1 < 0 ... the least integer greater
1425 * than or equal to arg1
1426 */
1427Datum
1429{
1430 float8 arg1 = PG_GETARG_FLOAT8(0);
1431 float8 result;
1432
1433 if (arg1 >= 0)
1434 result = floor(arg1);
1435 else
1436 result = -floor(-arg1);
1437
1438 PG_RETURN_FLOAT8(result);
1439}
1440
1441
1442/*
1443 * dsqrt - returns square root of arg1
1444 */
1445Datum
1447{
1448 float8 arg1 = PG_GETARG_FLOAT8(0);
1449 float8 result;
1450
1451 if (arg1 < 0)
1452 ereport(ERROR,
1453 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1454 errmsg("cannot take square root of a negative number")));
1455
1456 result = sqrt(arg1);
1457 if (unlikely(isinf(result)) && !isinf(arg1))
1459 if (unlikely(result == 0.0) && arg1 != 0.0)
1461
1462 PG_RETURN_FLOAT8(result);
1463}
1464
1465
1466/*
1467 * dcbrt - returns cube root of arg1
1468 */
1469Datum
1471{
1472 float8 arg1 = PG_GETARG_FLOAT8(0);
1473 float8 result;
1474
1475 result = cbrt(arg1);
1476 if (unlikely(isinf(result)) && !isinf(arg1))
1478 if (unlikely(result == 0.0) && arg1 != 0.0)
1480
1481 PG_RETURN_FLOAT8(result);
1482}
1483
1484
1485/*
1486 * dpow - returns pow(arg1,arg2)
1487 */
1488Datum
1490{
1491 float8 arg1 = PG_GETARG_FLOAT8(0);
1492 float8 arg2 = PG_GETARG_FLOAT8(1);
1493 float8 result;
1494
1495 /*
1496 * The POSIX spec says that NaN ^ 0 = 1, and 1 ^ NaN = 1, while all other
1497 * cases with NaN inputs yield NaN (with no error). Many older platforms
1498 * get one or more of these cases wrong, so deal with them via explicit
1499 * logic rather than trusting pow(3).
1500 */
1501 if (isnan(arg1))
1502 {
1503 if (isnan(arg2) || arg2 != 0.0)
1505 PG_RETURN_FLOAT8(1.0);
1506 }
1507 if (isnan(arg2))
1508 {
1509 if (arg1 != 1.0)
1511 PG_RETURN_FLOAT8(1.0);
1512 }
1513
1514 /*
1515 * The SQL spec requires that we emit a particular SQLSTATE error code for
1516 * certain error conditions. Specifically, we don't return a
1517 * divide-by-zero error code for 0 ^ -1.
1518 */
1519 if (arg1 == 0 && arg2 < 0)
1520 ereport(ERROR,
1521 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1522 errmsg("zero raised to a negative power is undefined")));
1523 if (arg1 < 0 && floor(arg2) != arg2)
1524 ereport(ERROR,
1525 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1526 errmsg("a negative number raised to a non-integer power yields a complex result")));
1527
1528 /*
1529 * We don't trust the platform's pow() to handle infinity cases per POSIX
1530 * spec either, so deal with those explicitly too. It's easier to handle
1531 * infinite y first, so that it doesn't matter if x is also infinite.
1532 */
1533 if (isinf(arg2))
1534 {
1535 float8 absx = fabs(arg1);
1536
1537 if (absx == 1.0)
1538 result = 1.0;
1539 else if (arg2 > 0.0) /* y = +Inf */
1540 {
1541 if (absx > 1.0)
1542 result = arg2;
1543 else
1544 result = 0.0;
1545 }
1546 else /* y = -Inf */
1547 {
1548 if (absx > 1.0)
1549 result = 0.0;
1550 else
1551 result = -arg2;
1552 }
1553 }
1554 else if (isinf(arg1))
1555 {
1556 if (arg2 == 0.0)
1557 result = 1.0;
1558 else if (arg1 > 0.0) /* x = +Inf */
1559 {
1560 if (arg2 > 0.0)
1561 result = arg1;
1562 else
1563 result = 0.0;
1564 }
1565 else /* x = -Inf */
1566 {
1567 /*
1568 * Per POSIX, the sign of the result depends on whether y is an
1569 * odd integer. Since x < 0, we already know from the previous
1570 * domain check that y is an integer. It is odd if y/2 is not
1571 * also an integer.
1572 */
1573 float8 halfy = arg2 / 2; /* should be computed exactly */
1574 bool yisoddinteger = (floor(halfy) != halfy);
1575
1576 if (arg2 > 0.0)
1577 result = yisoddinteger ? arg1 : -arg1;
1578 else
1579 result = yisoddinteger ? -0.0 : 0.0;
1580 }
1581 }
1582 else
1583 {
1584 /*
1585 * pow() sets errno on only some platforms, depending on whether it
1586 * follows _IEEE_, _POSIX_, _XOPEN_, or _SVID_, so we must check both
1587 * errno and invalid output values. (We can't rely on just the
1588 * latter, either; some old platforms return a large-but-finite
1589 * HUGE_VAL when reporting overflow.)
1590 */
1591 errno = 0;
1592 result = pow(arg1, arg2);
1593 if (errno == EDOM || isnan(result))
1594 {
1595 /*
1596 * We handled all possible domain errors above, so this should be
1597 * impossible. However, old glibc versions on x86 have a bug that
1598 * causes them to fail this way for abs(y) greater than 2^63:
1599 *
1600 * https://sourceware.org/bugzilla/show_bug.cgi?id=3866
1601 *
1602 * Hence, if we get here, assume y is finite but large (large
1603 * enough to be certainly even). The result should be 0 if x == 0,
1604 * 1.0 if abs(x) == 1.0, otherwise an overflow or underflow error.
1605 */
1606 if (arg1 == 0.0)
1607 result = 0.0; /* we already verified y is positive */
1608 else
1609 {
1610 float8 absx = fabs(arg1);
1611
1612 if (absx == 1.0)
1613 result = 1.0;
1614 else if (arg2 >= 0.0 ? (absx > 1.0) : (absx < 1.0))
1616 else
1618 }
1619 }
1620 else if (errno == ERANGE)
1621 {
1622 if (result != 0.0)
1624 else
1626 }
1627 else
1628 {
1629 if (unlikely(isinf(result)))
1631 if (unlikely(result == 0.0) && arg1 != 0.0)
1633 }
1634 }
1635
1636 PG_RETURN_FLOAT8(result);
1637}
1638
1639
1640/*
1641 * dexp - returns the exponential function of arg1
1642 */
1643Datum
1645{
1646 float8 arg1 = PG_GETARG_FLOAT8(0);
1647 float8 result;
1648
1649 /*
1650 * Handle NaN and Inf cases explicitly. This avoids needing to assume
1651 * that the platform's exp() conforms to POSIX for these cases, and it
1652 * removes some edge cases for the overflow checks below.
1653 */
1654 if (isnan(arg1))
1655 result = arg1;
1656 else if (isinf(arg1))
1657 {
1658 /* Per POSIX, exp(-Inf) is 0 */
1659 result = (arg1 > 0.0) ? arg1 : 0;
1660 }
1661 else
1662 {
1663 /*
1664 * On some platforms, exp() will not set errno but just return Inf or
1665 * zero to report overflow/underflow; therefore, test both cases.
1666 */
1667 errno = 0;
1668 result = exp(arg1);
1669 if (unlikely(errno == ERANGE))
1670 {
1671 if (result != 0.0)
1673 else
1675 }
1676 else if (unlikely(isinf(result)))
1678 else if (unlikely(result == 0.0))
1680 }
1681
1682 PG_RETURN_FLOAT8(result);
1683}
1684
1685
1686/*
1687 * dlog1 - returns the natural logarithm of arg1
1688 */
1689Datum
1691{
1692 float8 arg1 = PG_GETARG_FLOAT8(0);
1693 float8 result;
1694
1695 /*
1696 * Emit particular SQLSTATE error codes for ln(). This is required by the
1697 * SQL standard.
1698 */
1699 if (arg1 == 0.0)
1700 ereport(ERROR,
1701 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1702 errmsg("cannot take logarithm of zero")));
1703 if (arg1 < 0)
1704 ereport(ERROR,
1705 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1706 errmsg("cannot take logarithm of a negative number")));
1707
1708 result = log(arg1);
1709 if (unlikely(isinf(result)) && !isinf(arg1))
1711 if (unlikely(result == 0.0) && arg1 != 1.0)
1713
1714 PG_RETURN_FLOAT8(result);
1715}
1716
1717
1718/*
1719 * dlog10 - returns the base 10 logarithm of arg1
1720 */
1721Datum
1723{
1724 float8 arg1 = PG_GETARG_FLOAT8(0);
1725 float8 result;
1726
1727 /*
1728 * Emit particular SQLSTATE error codes for log(). The SQL spec doesn't
1729 * define log(), but it does define ln(), so it makes sense to emit the
1730 * same error code for an analogous error condition.
1731 */
1732 if (arg1 == 0.0)
1733 ereport(ERROR,
1734 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1735 errmsg("cannot take logarithm of zero")));
1736 if (arg1 < 0)
1737 ereport(ERROR,
1738 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1739 errmsg("cannot take logarithm of a negative number")));
1740
1741 result = log10(arg1);
1742 if (unlikely(isinf(result)) && !isinf(arg1))
1744 if (unlikely(result == 0.0) && arg1 != 1.0)
1746
1747 PG_RETURN_FLOAT8(result);
1748}
1749
1750
1751/*
1752 * dacos - returns the arccos of arg1 (radians)
1753 */
1754Datum
1756{
1757 float8 arg1 = PG_GETARG_FLOAT8(0);
1758 float8 result;
1759
1760 /* Per the POSIX spec, return NaN if the input is NaN */
1761 if (isnan(arg1))
1763
1764 /*
1765 * The principal branch of the inverse cosine function maps values in the
1766 * range [-1, 1] to values in the range [0, Pi], so we should reject any
1767 * inputs outside that range and the result will always be finite.
1768 */
1769 if (arg1 < -1.0 || arg1 > 1.0)
1770 ereport(ERROR,
1771 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1772 errmsg("input is out of range")));
1773
1774 result = acos(arg1);
1775 if (unlikely(isinf(result)))
1777
1778 PG_RETURN_FLOAT8(result);
1779}
1780
1781
1782/*
1783 * dasin - returns the arcsin of arg1 (radians)
1784 */
1785Datum
1787{
1788 float8 arg1 = PG_GETARG_FLOAT8(0);
1789 float8 result;
1790
1791 /* Per the POSIX spec, return NaN if the input is NaN */
1792 if (isnan(arg1))
1794
1795 /*
1796 * The principal branch of the inverse sine function maps values in the
1797 * range [-1, 1] to values in the range [-Pi/2, Pi/2], so we should reject
1798 * any inputs outside that range and the result will always be finite.
1799 */
1800 if (arg1 < -1.0 || arg1 > 1.0)
1801 ereport(ERROR,
1802 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1803 errmsg("input is out of range")));
1804
1805 result = asin(arg1);
1806 if (unlikely(isinf(result)))
1808
1809 PG_RETURN_FLOAT8(result);
1810}
1811
1812
1813/*
1814 * datan - returns the arctan of arg1 (radians)
1815 */
1816Datum
1818{
1819 float8 arg1 = PG_GETARG_FLOAT8(0);
1820 float8 result;
1821
1822 /* Per the POSIX spec, return NaN if the input is NaN */
1823 if (isnan(arg1))
1825
1826 /*
1827 * The principal branch of the inverse tangent function maps all inputs to
1828 * values in the range [-Pi/2, Pi/2], so the result should always be
1829 * finite, even if the input is infinite.
1830 */
1831 result = atan(arg1);
1832 if (unlikely(isinf(result)))
1834
1835 PG_RETURN_FLOAT8(result);
1836}
1837
1838
1839/*
1840 * atan2 - returns the arctan of arg1/arg2 (radians)
1841 */
1842Datum
1844{
1845 float8 arg1 = PG_GETARG_FLOAT8(0);
1846 float8 arg2 = PG_GETARG_FLOAT8(1);
1847 float8 result;
1848
1849 /* Per the POSIX spec, return NaN if either input is NaN */
1850 if (isnan(arg1) || isnan(arg2))
1852
1853 /*
1854 * atan2 maps all inputs to values in the range [-Pi, Pi], so the result
1855 * should always be finite, even if the inputs are infinite.
1856 */
1857 result = atan2(arg1, arg2);
1858 if (unlikely(isinf(result)))
1860
1861 PG_RETURN_FLOAT8(result);
1862}
1863
1864
1865/*
1866 * dcos - returns the cosine of arg1 (radians)
1867 */
1868Datum
1870{
1871 float8 arg1 = PG_GETARG_FLOAT8(0);
1872 float8 result;
1873
1874 /* Per the POSIX spec, return NaN if the input is NaN */
1875 if (isnan(arg1))
1877
1878 /*
1879 * cos() is periodic and so theoretically can work for all finite inputs,
1880 * but some implementations may choose to throw error if the input is so
1881 * large that there are no significant digits in the result. So we should
1882 * check for errors. POSIX allows an error to be reported either via
1883 * errno or via fetestexcept(), but currently we only support checking
1884 * errno. (fetestexcept() is rumored to report underflow unreasonably
1885 * early on some platforms, so it's not clear that believing it would be a
1886 * net improvement anyway.)
1887 *
1888 * For infinite inputs, POSIX specifies that the trigonometric functions
1889 * should return a domain error; but we won't notice that unless the
1890 * platform reports via errno, so also explicitly test for infinite
1891 * inputs.
1892 */
1893 errno = 0;
1894 result = cos(arg1);
1895 if (errno != 0 || isinf(arg1))
1896 ereport(ERROR,
1897 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1898 errmsg("input is out of range")));
1899 if (unlikely(isinf(result)))
1901
1902 PG_RETURN_FLOAT8(result);
1903}
1904
1905
1906/*
1907 * dcot - returns the cotangent of arg1 (radians)
1908 */
1909Datum
1911{
1912 float8 arg1 = PG_GETARG_FLOAT8(0);
1913 float8 result;
1914
1915 /* Per the POSIX spec, return NaN if the input is NaN */
1916 if (isnan(arg1))
1918
1919 /* Be sure to throw an error if the input is infinite --- see dcos() */
1920 errno = 0;
1921 result = tan(arg1);
1922 if (errno != 0 || isinf(arg1))
1923 ereport(ERROR,
1924 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1925 errmsg("input is out of range")));
1926
1927 result = 1.0 / result;
1928 /* Not checking for overflow because cot(0) == Inf */
1929
1930 PG_RETURN_FLOAT8(result);
1931}
1932
1933
1934/*
1935 * dsin - returns the sine of arg1 (radians)
1936 */
1937Datum
1939{
1940 float8 arg1 = PG_GETARG_FLOAT8(0);
1941 float8 result;
1942
1943 /* Per the POSIX spec, return NaN if the input is NaN */
1944 if (isnan(arg1))
1946
1947 /* Be sure to throw an error if the input is infinite --- see dcos() */
1948 errno = 0;
1949 result = sin(arg1);
1950 if (errno != 0 || isinf(arg1))
1951 ereport(ERROR,
1952 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1953 errmsg("input is out of range")));
1954 if (unlikely(isinf(result)))
1956
1957 PG_RETURN_FLOAT8(result);
1958}
1959
1960
1961/*
1962 * dtan - returns the tangent of arg1 (radians)
1963 */
1964Datum
1966{
1967 float8 arg1 = PG_GETARG_FLOAT8(0);
1968 float8 result;
1969
1970 /* Per the POSIX spec, return NaN if the input is NaN */
1971 if (isnan(arg1))
1973
1974 /* Be sure to throw an error if the input is infinite --- see dcos() */
1975 errno = 0;
1976 result = tan(arg1);
1977 if (errno != 0 || isinf(arg1))
1978 ereport(ERROR,
1979 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1980 errmsg("input is out of range")));
1981 /* Not checking for overflow because tan(pi/2) == Inf */
1982
1983 PG_RETURN_FLOAT8(result);
1984}
1985
1986
1987/* ========== DEGREE-BASED TRIGONOMETRIC FUNCTIONS ========== */
1988
1989
1990/*
1991 * Initialize the cached constants declared at the head of this file
1992 * (sin_30 etc). The fact that we need those at all, let alone need this
1993 * Rube-Goldberg-worthy method of initializing them, is because there are
1994 * compilers out there that will precompute expressions such as sin(constant)
1995 * using a sin() function different from what will be used at runtime. If we
1996 * want exact results, we must ensure that none of the scaling constants used
1997 * in the degree-based trig functions are computed that way. To do so, we
1998 * compute them from the variables degree_c_thirty etc, which are also really
1999 * constants, but the compiler cannot assume that.
2000 *
2001 * Other hazards we are trying to forestall with this kluge include the
2002 * possibility that compilers will rearrange the expressions, or compute
2003 * some intermediate results in registers wider than a standard double.
2004 *
2005 * In the places where we use these constants, the typical pattern is like
2006 * volatile float8 sin_x = sin(x * RADIANS_PER_DEGREE);
2007 * return (sin_x / sin_30);
2008 * where we hope to get a value of exactly 1.0 from the division when x = 30.
2009 * The volatile temporary variable is needed on machines with wide float
2010 * registers, to ensure that the result of sin(x) is rounded to double width
2011 * the same as the value of sin_30 has been. Experimentation with gcc shows
2012 * that marking the temp variable volatile is necessary to make the store and
2013 * reload actually happen; hopefully the same trick works for other compilers.
2014 * (gcc's documentation suggests using the -ffloat-store compiler switch to
2015 * ensure this, but that is compiler-specific and it also pessimizes code in
2016 * many places where we don't care about this.)
2017 */
2018static void
2020{
2025 atan_1_0 = atan(degree_c_one);
2028 degree_consts_set = true;
2029}
2030
2031#define INIT_DEGREE_CONSTANTS() \
2032do { \
2033 if (!degree_consts_set) \
2034 init_degree_constants(); \
2035} while(0)
2036
2037
2038/*
2039 * asind_q1 - returns the inverse sine of x in degrees, for x in
2040 * the range [0, 1]. The result is an angle in the
2041 * first quadrant --- [0, 90] degrees.
2042 *
2043 * For the 3 special case inputs (0, 0.5 and 1), this
2044 * function will return exact values (0, 30 and 90
2045 * degrees respectively).
2046 */
2047static double
2049{
2050 /*
2051 * Stitch together inverse sine and cosine functions for the ranges [0,
2052 * 0.5] and (0.5, 1]. Each expression below is guaranteed to return
2053 * exactly 30 for x=0.5, so the result is a continuous monotonic function
2054 * over the full range.
2055 */
2056 if (x <= 0.5)
2057 {
2058 volatile float8 asin_x = asin(x);
2059
2060 return (asin_x / asin_0_5) * 30.0;
2061 }
2062 else
2063 {
2064 volatile float8 acos_x = acos(x);
2065
2066 return 90.0 - (acos_x / acos_0_5) * 60.0;
2067 }
2068}
2069
2070
2071/*
2072 * acosd_q1 - returns the inverse cosine of x in degrees, for x in
2073 * the range [0, 1]. The result is an angle in the
2074 * first quadrant --- [0, 90] degrees.
2075 *
2076 * For the 3 special case inputs (0, 0.5 and 1), this
2077 * function will return exact values (0, 60 and 90
2078 * degrees respectively).
2079 */
2080static double
2082{
2083 /*
2084 * Stitch together inverse sine and cosine functions for the ranges [0,
2085 * 0.5] and (0.5, 1]. Each expression below is guaranteed to return
2086 * exactly 60 for x=0.5, so the result is a continuous monotonic function
2087 * over the full range.
2088 */
2089 if (x <= 0.5)
2090 {
2091 volatile float8 asin_x = asin(x);
2092
2093 return 90.0 - (asin_x / asin_0_5) * 30.0;
2094 }
2095 else
2096 {
2097 volatile float8 acos_x = acos(x);
2098
2099 return (acos_x / acos_0_5) * 60.0;
2100 }
2101}
2102
2103
2104/*
2105 * dacosd - returns the arccos of arg1 (degrees)
2106 */
2107Datum
2109{
2110 float8 arg1 = PG_GETARG_FLOAT8(0);
2111 float8 result;
2112
2113 /* Per the POSIX spec, return NaN if the input is NaN */
2114 if (isnan(arg1))
2116
2118
2119 /*
2120 * The principal branch of the inverse cosine function maps values in the
2121 * range [-1, 1] to values in the range [0, 180], so we should reject any
2122 * inputs outside that range and the result will always be finite.
2123 */
2124 if (arg1 < -1.0 || arg1 > 1.0)
2125 ereport(ERROR,
2126 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2127 errmsg("input is out of range")));
2128
2129 if (arg1 >= 0.0)
2130 result = acosd_q1(arg1);
2131 else
2132 result = 90.0 + asind_q1(-arg1);
2133
2134 if (unlikely(isinf(result)))
2136
2137 PG_RETURN_FLOAT8(result);
2138}
2139
2140
2141/*
2142 * dasind - returns the arcsin of arg1 (degrees)
2143 */
2144Datum
2146{
2147 float8 arg1 = PG_GETARG_FLOAT8(0);
2148 float8 result;
2149
2150 /* Per the POSIX spec, return NaN if the input is NaN */
2151 if (isnan(arg1))
2153
2155
2156 /*
2157 * The principal branch of the inverse sine function maps values in the
2158 * range [-1, 1] to values in the range [-90, 90], so we should reject any
2159 * inputs outside that range and the result will always be finite.
2160 */
2161 if (arg1 < -1.0 || arg1 > 1.0)
2162 ereport(ERROR,
2163 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2164 errmsg("input is out of range")));
2165
2166 if (arg1 >= 0.0)
2167 result = asind_q1(arg1);
2168 else
2169 result = -asind_q1(-arg1);
2170
2171 if (unlikely(isinf(result)))
2173
2174 PG_RETURN_FLOAT8(result);
2175}
2176
2177
2178/*
2179 * datand - returns the arctan of arg1 (degrees)
2180 */
2181Datum
2183{
2184 float8 arg1 = PG_GETARG_FLOAT8(0);
2185 float8 result;
2186 volatile float8 atan_arg1;
2187
2188 /* Per the POSIX spec, return NaN if the input is NaN */
2189 if (isnan(arg1))
2191
2193
2194 /*
2195 * The principal branch of the inverse tangent function maps all inputs to
2196 * values in the range [-90, 90], so the result should always be finite,
2197 * even if the input is infinite. Additionally, we take care to ensure
2198 * than when arg1 is 1, the result is exactly 45.
2199 */
2200 atan_arg1 = atan(arg1);
2201 result = (atan_arg1 / atan_1_0) * 45.0;
2202
2203 if (unlikely(isinf(result)))
2205
2206 PG_RETURN_FLOAT8(result);
2207}
2208
2209
2210/*
2211 * atan2d - returns the arctan of arg1/arg2 (degrees)
2212 */
2213Datum
2215{
2216 float8 arg1 = PG_GETARG_FLOAT8(0);
2217 float8 arg2 = PG_GETARG_FLOAT8(1);
2218 float8 result;
2219 volatile float8 atan2_arg1_arg2;
2220
2221 /* Per the POSIX spec, return NaN if either input is NaN */
2222 if (isnan(arg1) || isnan(arg2))
2224
2226
2227 /*
2228 * atan2d maps all inputs to values in the range [-180, 180], so the
2229 * result should always be finite, even if the inputs are infinite.
2230 *
2231 * Note: this coding assumes that atan(1.0) is a suitable scaling constant
2232 * to get an exact result from atan2(). This might well fail on us at
2233 * some point, requiring us to decide exactly what inputs we think we're
2234 * going to guarantee an exact result for.
2235 */
2236 atan2_arg1_arg2 = atan2(arg1, arg2);
2237 result = (atan2_arg1_arg2 / atan_1_0) * 45.0;
2238
2239 if (unlikely(isinf(result)))
2241
2242 PG_RETURN_FLOAT8(result);
2243}
2244
2245
2246/*
2247 * sind_0_to_30 - returns the sine of an angle that lies between 0 and
2248 * 30 degrees. This will return exactly 0 when x is 0,
2249 * and exactly 0.5 when x is 30 degrees.
2250 */
2251static double
2253{
2254 volatile float8 sin_x = sin(x * RADIANS_PER_DEGREE);
2255
2256 return (sin_x / sin_30) / 2.0;
2257}
2258
2259
2260/*
2261 * cosd_0_to_60 - returns the cosine of an angle that lies between 0
2262 * and 60 degrees. This will return exactly 1 when x
2263 * is 0, and exactly 0.5 when x is 60 degrees.
2264 */
2265static double
2267{
2268 volatile float8 one_minus_cos_x = 1.0 - cos(x * RADIANS_PER_DEGREE);
2269
2270 return 1.0 - (one_minus_cos_x / one_minus_cos_60) / 2.0;
2271}
2272
2273
2274/*
2275 * sind_q1 - returns the sine of an angle in the first quadrant
2276 * (0 to 90 degrees).
2277 */
2278static double
2279sind_q1(double x)
2280{
2281 /*
2282 * Stitch together the sine and cosine functions for the ranges [0, 30]
2283 * and (30, 90]. These guarantee to return exact answers at their
2284 * endpoints, so the overall result is a continuous monotonic function
2285 * that gives exact results when x = 0, 30 and 90 degrees.
2286 */
2287 if (x <= 30.0)
2288 return sind_0_to_30(x);
2289 else
2290 return cosd_0_to_60(90.0 - x);
2291}
2292
2293
2294/*
2295 * cosd_q1 - returns the cosine of an angle in the first quadrant
2296 * (0 to 90 degrees).
2297 */
2298static double
2299cosd_q1(double x)
2300{
2301 /*
2302 * Stitch together the sine and cosine functions for the ranges [0, 60]
2303 * and (60, 90]. These guarantee to return exact answers at their
2304 * endpoints, so the overall result is a continuous monotonic function
2305 * that gives exact results when x = 0, 60 and 90 degrees.
2306 */
2307 if (x <= 60.0)
2308 return cosd_0_to_60(x);
2309 else
2310 return sind_0_to_30(90.0 - x);
2311}
2312
2313
2314/*
2315 * dcosd - returns the cosine of arg1 (degrees)
2316 */
2317Datum
2319{
2320 float8 arg1 = PG_GETARG_FLOAT8(0);
2321 float8 result;
2322 int sign = 1;
2323
2324 /*
2325 * Per the POSIX spec, return NaN if the input is NaN and throw an error
2326 * if the input is infinite.
2327 */
2328 if (isnan(arg1))
2330
2331 if (isinf(arg1))
2332 ereport(ERROR,
2333 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2334 errmsg("input is out of range")));
2335
2337
2338 /* Reduce the range of the input to [0,90] degrees */
2339 arg1 = fmod(arg1, 360.0);
2340
2341 if (arg1 < 0.0)
2342 {
2343 /* cosd(-x) = cosd(x) */
2344 arg1 = -arg1;
2345 }
2346
2347 if (arg1 > 180.0)
2348 {
2349 /* cosd(360-x) = cosd(x) */
2350 arg1 = 360.0 - arg1;
2351 }
2352
2353 if (arg1 > 90.0)
2354 {
2355 /* cosd(180-x) = -cosd(x) */
2356 arg1 = 180.0 - arg1;
2357 sign = -sign;
2358 }
2359
2360 result = sign * cosd_q1(arg1);
2361
2362 if (unlikely(isinf(result)))
2364
2365 PG_RETURN_FLOAT8(result);
2366}
2367
2368
2369/*
2370 * dcotd - returns the cotangent of arg1 (degrees)
2371 */
2372Datum
2374{
2375 float8 arg1 = PG_GETARG_FLOAT8(0);
2376 float8 result;
2377 volatile float8 cot_arg1;
2378 int sign = 1;
2379
2380 /*
2381 * Per the POSIX spec, return NaN if the input is NaN and throw an error
2382 * if the input is infinite.
2383 */
2384 if (isnan(arg1))
2386
2387 if (isinf(arg1))
2388 ereport(ERROR,
2389 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2390 errmsg("input is out of range")));
2391
2393
2394 /* Reduce the range of the input to [0,90] degrees */
2395 arg1 = fmod(arg1, 360.0);
2396
2397 if (arg1 < 0.0)
2398 {
2399 /* cotd(-x) = -cotd(x) */
2400 arg1 = -arg1;
2401 sign = -sign;
2402 }
2403
2404 if (arg1 > 180.0)
2405 {
2406 /* cotd(360-x) = -cotd(x) */
2407 arg1 = 360.0 - arg1;
2408 sign = -sign;
2409 }
2410
2411 if (arg1 > 90.0)
2412 {
2413 /* cotd(180-x) = -cotd(x) */
2414 arg1 = 180.0 - arg1;
2415 sign = -sign;
2416 }
2417
2418 cot_arg1 = cosd_q1(arg1) / sind_q1(arg1);
2419 result = sign * (cot_arg1 / cot_45);
2420
2421 /*
2422 * On some machines we get cotd(270) = minus zero, but this isn't always
2423 * true. For portability, and because the user constituency for this
2424 * function probably doesn't want minus zero, force it to plain zero.
2425 */
2426 if (result == 0.0)
2427 result = 0.0;
2428
2429 /* Not checking for overflow because cotd(0) == Inf */
2430
2431 PG_RETURN_FLOAT8(result);
2432}
2433
2434
2435/*
2436 * dsind - returns the sine of arg1 (degrees)
2437 */
2438Datum
2440{
2441 float8 arg1 = PG_GETARG_FLOAT8(0);
2442 float8 result;
2443 int sign = 1;
2444
2445 /*
2446 * Per the POSIX spec, return NaN if the input is NaN and throw an error
2447 * if the input is infinite.
2448 */
2449 if (isnan(arg1))
2451
2452 if (isinf(arg1))
2453 ereport(ERROR,
2454 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2455 errmsg("input is out of range")));
2456
2458
2459 /* Reduce the range of the input to [0,90] degrees */
2460 arg1 = fmod(arg1, 360.0);
2461
2462 if (arg1 < 0.0)
2463 {
2464 /* sind(-x) = -sind(x) */
2465 arg1 = -arg1;
2466 sign = -sign;
2467 }
2468
2469 if (arg1 > 180.0)
2470 {
2471 /* sind(360-x) = -sind(x) */
2472 arg1 = 360.0 - arg1;
2473 sign = -sign;
2474 }
2475
2476 if (arg1 > 90.0)
2477 {
2478 /* sind(180-x) = sind(x) */
2479 arg1 = 180.0 - arg1;
2480 }
2481
2482 result = sign * sind_q1(arg1);
2483
2484 if (unlikely(isinf(result)))
2486
2487 PG_RETURN_FLOAT8(result);
2488}
2489
2490
2491/*
2492 * dtand - returns the tangent of arg1 (degrees)
2493 */
2494Datum
2496{
2497 float8 arg1 = PG_GETARG_FLOAT8(0);
2498 float8 result;
2499 volatile float8 tan_arg1;
2500 int sign = 1;
2501
2502 /*
2503 * Per the POSIX spec, return NaN if the input is NaN and throw an error
2504 * if the input is infinite.
2505 */
2506 if (isnan(arg1))
2508
2509 if (isinf(arg1))
2510 ereport(ERROR,
2511 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2512 errmsg("input is out of range")));
2513
2515
2516 /* Reduce the range of the input to [0,90] degrees */
2517 arg1 = fmod(arg1, 360.0);
2518
2519 if (arg1 < 0.0)
2520 {
2521 /* tand(-x) = -tand(x) */
2522 arg1 = -arg1;
2523 sign = -sign;
2524 }
2525
2526 if (arg1 > 180.0)
2527 {
2528 /* tand(360-x) = -tand(x) */
2529 arg1 = 360.0 - arg1;
2530 sign = -sign;
2531 }
2532
2533 if (arg1 > 90.0)
2534 {
2535 /* tand(180-x) = -tand(x) */
2536 arg1 = 180.0 - arg1;
2537 sign = -sign;
2538 }
2539
2540 tan_arg1 = sind_q1(arg1) / cosd_q1(arg1);
2541 result = sign * (tan_arg1 / tan_45);
2542
2543 /*
2544 * On some machines we get tand(180) = minus zero, but this isn't always
2545 * true. For portability, and because the user constituency for this
2546 * function probably doesn't want minus zero, force it to plain zero.
2547 */
2548 if (result == 0.0)
2549 result = 0.0;
2550
2551 /* Not checking for overflow because tand(90) == Inf */
2552
2553 PG_RETURN_FLOAT8(result);
2554}
2555
2556
2557/*
2558 * degrees - returns degrees converted from radians
2559 */
2560Datum
2562{
2563 float8 arg1 = PG_GETARG_FLOAT8(0);
2564
2566}
2567
2568
2569/*
2570 * dpi - returns the constant PI
2571 */
2572Datum
2574{
2576}
2577
2578
2579/*
2580 * radians - returns radians converted from degrees
2581 */
2582Datum
2584{
2585 float8 arg1 = PG_GETARG_FLOAT8(0);
2586
2588}
2589
2590
2591/* ========== HYPERBOLIC FUNCTIONS ========== */
2592
2593
2594/*
2595 * dsinh - returns the hyperbolic sine of arg1
2596 */
2597Datum
2599{
2600 float8 arg1 = PG_GETARG_FLOAT8(0);
2601 float8 result;
2602
2603 errno = 0;
2604 result = sinh(arg1);
2605
2606 /*
2607 * if an ERANGE error occurs, it means there is an overflow. For sinh,
2608 * the result should be either -infinity or infinity, depending on the
2609 * sign of arg1.
2610 */
2611 if (errno == ERANGE)
2612 {
2613 if (arg1 < 0)
2614 result = -get_float8_infinity();
2615 else
2616 result = get_float8_infinity();
2617 }
2618
2619 PG_RETURN_FLOAT8(result);
2620}
2621
2622
2623/*
2624 * dcosh - returns the hyperbolic cosine of arg1
2625 */
2626Datum
2628{
2629 float8 arg1 = PG_GETARG_FLOAT8(0);
2630 float8 result;
2631
2632 errno = 0;
2633 result = cosh(arg1);
2634
2635 /*
2636 * if an ERANGE error occurs, it means there is an overflow. As cosh is
2637 * always positive, it always means the result is positive infinity.
2638 */
2639 if (errno == ERANGE)
2640 result = get_float8_infinity();
2641
2642 if (unlikely(result == 0.0))
2644
2645 PG_RETURN_FLOAT8(result);
2646}
2647
2648/*
2649 * dtanh - returns the hyperbolic tangent of arg1
2650 */
2651Datum
2653{
2654 float8 arg1 = PG_GETARG_FLOAT8(0);
2655 float8 result;
2656
2657 /*
2658 * For tanh, we don't need an errno check because it never overflows.
2659 */
2660 result = tanh(arg1);
2661
2662 if (unlikely(isinf(result)))
2664
2665 PG_RETURN_FLOAT8(result);
2666}
2667
2668/*
2669 * dasinh - returns the inverse hyperbolic sine of arg1
2670 */
2671Datum
2673{
2674 float8 arg1 = PG_GETARG_FLOAT8(0);
2675 float8 result;
2676
2677 /*
2678 * For asinh, we don't need an errno check because it never overflows.
2679 */
2680 result = asinh(arg1);
2681
2682 PG_RETURN_FLOAT8(result);
2683}
2684
2685/*
2686 * dacosh - returns the inverse hyperbolic cosine of arg1
2687 */
2688Datum
2690{
2691 float8 arg1 = PG_GETARG_FLOAT8(0);
2692 float8 result;
2693
2694 /*
2695 * acosh is only defined for inputs >= 1.0. By checking this ourselves,
2696 * we need not worry about checking for an EDOM error, which is a good
2697 * thing because some implementations will report that for NaN. Otherwise,
2698 * no error is possible.
2699 */
2700 if (arg1 < 1.0)
2701 ereport(ERROR,
2702 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2703 errmsg("input is out of range")));
2704
2705 result = acosh(arg1);
2706
2707 PG_RETURN_FLOAT8(result);
2708}
2709
2710/*
2711 * datanh - returns the inverse hyperbolic tangent of arg1
2712 */
2713Datum
2715{
2716 float8 arg1 = PG_GETARG_FLOAT8(0);
2717 float8 result;
2718
2719 /*
2720 * atanh is only defined for inputs between -1 and 1. By checking this
2721 * ourselves, we need not worry about checking for an EDOM error, which is
2722 * a good thing because some implementations will report that for NaN.
2723 */
2724 if (arg1 < -1.0 || arg1 > 1.0)
2725 ereport(ERROR,
2726 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2727 errmsg("input is out of range")));
2728
2729 /*
2730 * Also handle the infinity cases ourselves; this is helpful because old
2731 * glibc versions may produce the wrong errno for this. All other inputs
2732 * cannot produce an error.
2733 */
2734 if (arg1 == -1.0)
2735 result = -get_float8_infinity();
2736 else if (arg1 == 1.0)
2737 result = get_float8_infinity();
2738 else
2739 result = atanh(arg1);
2740
2741 PG_RETURN_FLOAT8(result);
2742}
2743
2744
2745/* ========== ERROR FUNCTIONS ========== */
2746
2747
2748/*
2749 * derf - returns the error function: erf(arg1)
2750 */
2751Datum
2753{
2754 float8 arg1 = PG_GETARG_FLOAT8(0);
2755 float8 result;
2756
2757 /*
2758 * For erf, we don't need an errno check because it never overflows.
2759 */
2760 result = erf(arg1);
2761
2762 if (unlikely(isinf(result)))
2764
2765 PG_RETURN_FLOAT8(result);
2766}
2767
2768/*
2769 * derfc - returns the complementary error function: 1 - erf(arg1)
2770 */
2771Datum
2773{
2774 float8 arg1 = PG_GETARG_FLOAT8(0);
2775 float8 result;
2776
2777 /*
2778 * For erfc, we don't need an errno check because it never overflows.
2779 */
2780 result = erfc(arg1);
2781
2782 if (unlikely(isinf(result)))
2784
2785 PG_RETURN_FLOAT8(result);
2786}
2787
2788
2789/* ========== GAMMA FUNCTIONS ========== */
2790
2791
2792/*
2793 * dgamma - returns the gamma function of arg1
2794 */
2795Datum
2797{
2798 float8 arg1 = PG_GETARG_FLOAT8(0);
2799 float8 result;
2800
2801 /*
2802 * Handle NaN and Inf cases explicitly. This simplifies the overflow
2803 * checks on platforms that do not set errno.
2804 */
2805 if (isnan(arg1))
2806 result = arg1;
2807 else if (isinf(arg1))
2808 {
2809 /* Per POSIX, an input of -Inf causes a domain error */
2810 if (arg1 < 0)
2811 {
2813 result = get_float8_nan(); /* keep compiler quiet */
2814 }
2815 else
2816 result = arg1;
2817 }
2818 else
2819 {
2820 /*
2821 * Note: the POSIX/C99 gamma function is called "tgamma", not "gamma".
2822 *
2823 * On some platforms, tgamma() will not set errno but just return Inf,
2824 * NaN, or zero to report overflow/underflow; therefore, test those
2825 * cases explicitly (note that, like the exponential function, the
2826 * gamma function has no zeros).
2827 */
2828 errno = 0;
2829 result = tgamma(arg1);
2830
2831 if (errno != 0 || isinf(result) || isnan(result))
2832 {
2833 if (result != 0.0)
2835 else
2837 }
2838 else if (result == 0.0)
2840 }
2841
2842 PG_RETURN_FLOAT8(result);
2843}
2844
2845
2846/*
2847 * dlgamma - natural logarithm of absolute value of gamma of arg1
2848 */
2849Datum
2851{
2852 float8 arg1 = PG_GETARG_FLOAT8(0);
2853 float8 result;
2854
2855 /*
2856 * Note: lgamma may not be thread-safe because it may write to a global
2857 * variable signgam, which may not be thread-local. However, this doesn't
2858 * matter to us, since we don't use signgam.
2859 */
2860 errno = 0;
2861 result = lgamma(arg1);
2862
2863 /*
2864 * If an ERANGE error occurs, it means there was an overflow or a pole
2865 * error (which happens for zero and negative integer inputs).
2866 *
2867 * On some platforms, lgamma() will not set errno but just return infinity
2868 * to report overflow, but it should never underflow.
2869 */
2870 if (errno == ERANGE || (isinf(result) && !isinf(arg1)))
2872
2873 PG_RETURN_FLOAT8(result);
2874}
2875
2876
2877
2878/*
2879 * =========================
2880 * FLOAT AGGREGATE OPERATORS
2881 * =========================
2882 *
2883 * float8_accum - accumulate for AVG(), variance aggregates, etc.
2884 * float4_accum - same, but input data is float4
2885 * float8_avg - produce final result for float AVG()
2886 * float8_var_samp - produce final result for float VAR_SAMP()
2887 * float8_var_pop - produce final result for float VAR_POP()
2888 * float8_stddev_samp - produce final result for float STDDEV_SAMP()
2889 * float8_stddev_pop - produce final result for float STDDEV_POP()
2890 *
2891 * The naive schoolbook implementation of these aggregates works by
2892 * accumulating sum(X) and sum(X^2). However, this approach suffers from
2893 * large rounding errors in the final computation of quantities like the
2894 * population variance (N*sum(X^2) - sum(X)^2) / N^2, since each of the
2895 * intermediate terms is potentially very large, while the difference is often
2896 * quite small.
2897 *
2898 * Instead we use the Youngs-Cramer algorithm [1] which works by accumulating
2899 * Sx=sum(X) and Sxx=sum((X-Sx/N)^2), using a numerically stable algorithm to
2900 * incrementally update those quantities. The final computations of each of
2901 * the aggregate values is then trivial and gives more accurate results (for
2902 * example, the population variance is just Sxx/N). This algorithm is also
2903 * fairly easy to generalize to allow parallel execution without loss of
2904 * precision (see, for example, [2]). For more details, and a comparison of
2905 * this with other algorithms, see [3].
2906 *
2907 * The transition datatype for all these aggregates is a 3-element array
2908 * of float8, holding the values N, Sx, Sxx in that order.
2909 *
2910 * Note that we represent N as a float to avoid having to build a special
2911 * datatype. Given a reasonable floating-point implementation, there should
2912 * be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the
2913 * user will have doubtless lost interest anyway...)
2914 *
2915 * [1] Some Results Relevant to Choice of Sum and Sum-of-Product Algorithms,
2916 * E. A. Youngs and E. M. Cramer, Technometrics Vol 13, No 3, August 1971.
2917 *
2918 * [2] Updating Formulae and a Pairwise Algorithm for Computing Sample
2919 * Variances, T. F. Chan, G. H. Golub & R. J. LeVeque, COMPSTAT 1982.
2920 *
2921 * [3] Numerically Stable Parallel Computation of (Co-)Variance, Erich
2922 * Schubert and Michael Gertz, Proceedings of the 30th International
2923 * Conference on Scientific and Statistical Database Management, 2018.
2924 */
2925
2926static float8 *
2927check_float8_array(ArrayType *transarray, const char *caller, int n)
2928{
2929 /*
2930 * We expect the input to be an N-element float array; verify that. We
2931 * don't need to use deconstruct_array() since the array data is just
2932 * going to look like a C array of N float8 values.
2933 */
2934 if (ARR_NDIM(transarray) != 1 ||
2935 ARR_DIMS(transarray)[0] != n ||
2936 ARR_HASNULL(transarray) ||
2937 ARR_ELEMTYPE(transarray) != FLOAT8OID)
2938 elog(ERROR, "%s: expected %d-element float8 array", caller, n);
2939 return (float8 *) ARR_DATA_PTR(transarray);
2940}
2941
2942/*
2943 * float8_combine
2944 *
2945 * An aggregate combine function used to combine two 3 fields
2946 * aggregate transition data into a single transition data.
2947 * This function is used only in two stage aggregation and
2948 * shouldn't be called outside aggregate context.
2949 */
2950Datum
2952{
2953 ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
2954 ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
2955 float8 *transvalues1;
2956 float8 *transvalues2;
2957 float8 N1,
2958 Sx1,
2959 Sxx1,
2960 N2,
2961 Sx2,
2962 Sxx2,
2963 tmp,
2964 N,
2965 Sx,
2966 Sxx;
2967
2968 transvalues1 = check_float8_array(transarray1, "float8_combine", 3);
2969 transvalues2 = check_float8_array(transarray2, "float8_combine", 3);
2970
2971 N1 = transvalues1[0];
2972 Sx1 = transvalues1[1];
2973 Sxx1 = transvalues1[2];
2974
2975 N2 = transvalues2[0];
2976 Sx2 = transvalues2[1];
2977 Sxx2 = transvalues2[2];
2978
2979 /*--------------------
2980 * The transition values combine using a generalization of the
2981 * Youngs-Cramer algorithm as follows:
2982 *
2983 * N = N1 + N2
2984 * Sx = Sx1 + Sx2
2985 * Sxx = Sxx1 + Sxx2 + N1 * N2 * (Sx1/N1 - Sx2/N2)^2 / N;
2986 *
2987 * It's worth handling the special cases N1 = 0 and N2 = 0 separately
2988 * since those cases are trivial, and we then don't need to worry about
2989 * division-by-zero errors in the general case.
2990 *--------------------
2991 */
2992 if (N1 == 0.0)
2993 {
2994 N = N2;
2995 Sx = Sx2;
2996 Sxx = Sxx2;
2997 }
2998 else if (N2 == 0.0)
2999 {
3000 N = N1;
3001 Sx = Sx1;
3002 Sxx = Sxx1;
3003 }
3004 else
3005 {
3006 N = N1 + N2;
3007 Sx = float8_pl(Sx1, Sx2);
3008 tmp = Sx1 / N1 - Sx2 / N2;
3009 Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp * tmp / N;
3010 if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
3012 }
3013
3014 /*
3015 * If we're invoked as an aggregate, we can cheat and modify our first
3016 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3017 * new array with the updated transition data and return it.
3018 */
3019 if (AggCheckCallContext(fcinfo, NULL))
3020 {
3021 transvalues1[0] = N;
3022 transvalues1[1] = Sx;
3023 transvalues1[2] = Sxx;
3024
3025 PG_RETURN_ARRAYTYPE_P(transarray1);
3026 }
3027 else
3028 {
3029 Datum transdatums[3];
3030 ArrayType *result;
3031
3032 transdatums[0] = Float8GetDatumFast(N);
3033 transdatums[1] = Float8GetDatumFast(Sx);
3034 transdatums[2] = Float8GetDatumFast(Sxx);
3035
3036 result = construct_array_builtin(transdatums, 3, FLOAT8OID);
3037
3038 PG_RETURN_ARRAYTYPE_P(result);
3039 }
3040}
3041
3042Datum
3044{
3045 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3047 float8 *transvalues;
3048 float8 N,
3049 Sx,
3050 Sxx,
3051 tmp;
3052
3053 transvalues = check_float8_array(transarray, "float8_accum", 3);
3054 N = transvalues[0];
3055 Sx = transvalues[1];
3056 Sxx = transvalues[2];
3057
3058 /*
3059 * Use the Youngs-Cramer algorithm to incorporate the new value into the
3060 * transition values.
3061 */
3062 N += 1.0;
3063 Sx += newval;
3064 if (transvalues[0] > 0.0)
3065 {
3066 tmp = newval * N - Sx;
3067 Sxx += tmp * tmp / (N * transvalues[0]);
3068
3069 /*
3070 * Overflow check. We only report an overflow error when finite
3071 * inputs lead to infinite results. Note also that Sxx should be NaN
3072 * if any of the inputs are infinite, so we intentionally prevent Sxx
3073 * from becoming infinite.
3074 */
3075 if (isinf(Sx) || isinf(Sxx))
3076 {
3077 if (!isinf(transvalues[1]) && !isinf(newval))
3079
3080 Sxx = get_float8_nan();
3081 }
3082 }
3083 else
3084 {
3085 /*
3086 * At the first input, we normally can leave Sxx as 0. However, if
3087 * the first input is Inf or NaN, we'd better force Sxx to NaN;
3088 * otherwise we will falsely report variance zero when there are no
3089 * more inputs.
3090 */
3091 if (isnan(newval) || isinf(newval))
3092 Sxx = get_float8_nan();
3093 }
3094
3095 /*
3096 * If we're invoked as an aggregate, we can cheat and modify our first
3097 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3098 * new array with the updated transition data and return it.
3099 */
3100 if (AggCheckCallContext(fcinfo, NULL))
3101 {
3102 transvalues[0] = N;
3103 transvalues[1] = Sx;
3104 transvalues[2] = Sxx;
3105
3106 PG_RETURN_ARRAYTYPE_P(transarray);
3107 }
3108 else
3109 {
3110 Datum transdatums[3];
3111 ArrayType *result;
3112
3113 transdatums[0] = Float8GetDatumFast(N);
3114 transdatums[1] = Float8GetDatumFast(Sx);
3115 transdatums[2] = Float8GetDatumFast(Sxx);
3116
3117 result = construct_array_builtin(transdatums, 3, FLOAT8OID);
3118
3119 PG_RETURN_ARRAYTYPE_P(result);
3120 }
3121}
3122
3123Datum
3125{
3126 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3127
3128 /* do computations as float8 */
3130 float8 *transvalues;
3131 float8 N,
3132 Sx,
3133 Sxx,
3134 tmp;
3135
3136 transvalues = check_float8_array(transarray, "float4_accum", 3);
3137 N = transvalues[0];
3138 Sx = transvalues[1];
3139 Sxx = transvalues[2];
3140
3141 /*
3142 * Use the Youngs-Cramer algorithm to incorporate the new value into the
3143 * transition values.
3144 */
3145 N += 1.0;
3146 Sx += newval;
3147 if (transvalues[0] > 0.0)
3148 {
3149 tmp = newval * N - Sx;
3150 Sxx += tmp * tmp / (N * transvalues[0]);
3151
3152 /*
3153 * Overflow check. We only report an overflow error when finite
3154 * inputs lead to infinite results. Note also that Sxx should be NaN
3155 * if any of the inputs are infinite, so we intentionally prevent Sxx
3156 * from becoming infinite.
3157 */
3158 if (isinf(Sx) || isinf(Sxx))
3159 {
3160 if (!isinf(transvalues[1]) && !isinf(newval))
3162
3163 Sxx = get_float8_nan();
3164 }
3165 }
3166 else
3167 {
3168 /*
3169 * At the first input, we normally can leave Sxx as 0. However, if
3170 * the first input is Inf or NaN, we'd better force Sxx to NaN;
3171 * otherwise we will falsely report variance zero when there are no
3172 * more inputs.
3173 */
3174 if (isnan(newval) || isinf(newval))
3175 Sxx = get_float8_nan();
3176 }
3177
3178 /*
3179 * If we're invoked as an aggregate, we can cheat and modify our first
3180 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3181 * new array with the updated transition data and return it.
3182 */
3183 if (AggCheckCallContext(fcinfo, NULL))
3184 {
3185 transvalues[0] = N;
3186 transvalues[1] = Sx;
3187 transvalues[2] = Sxx;
3188
3189 PG_RETURN_ARRAYTYPE_P(transarray);
3190 }
3191 else
3192 {
3193 Datum transdatums[3];
3194 ArrayType *result;
3195
3196 transdatums[0] = Float8GetDatumFast(N);
3197 transdatums[1] = Float8GetDatumFast(Sx);
3198 transdatums[2] = Float8GetDatumFast(Sxx);
3199
3200 result = construct_array_builtin(transdatums, 3, FLOAT8OID);
3201
3202 PG_RETURN_ARRAYTYPE_P(result);
3203 }
3204}
3205
3206Datum
3208{
3209 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3210 float8 *transvalues;
3211 float8 N,
3212 Sx;
3213
3214 transvalues = check_float8_array(transarray, "float8_avg", 3);
3215 N = transvalues[0];
3216 Sx = transvalues[1];
3217 /* ignore Sxx */
3218
3219 /* SQL defines AVG of no values to be NULL */
3220 if (N == 0.0)
3222
3223 PG_RETURN_FLOAT8(Sx / N);
3224}
3225
3226Datum
3228{
3229 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3230 float8 *transvalues;
3231 float8 N,
3232 Sxx;
3233
3234 transvalues = check_float8_array(transarray, "float8_var_pop", 3);
3235 N = transvalues[0];
3236 /* ignore Sx */
3237 Sxx = transvalues[2];
3238
3239 /* Population variance is undefined when N is 0, so return NULL */
3240 if (N == 0.0)
3242
3243 /* Note that Sxx is guaranteed to be non-negative */
3244
3245 PG_RETURN_FLOAT8(Sxx / N);
3246}
3247
3248Datum
3250{
3251 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3252 float8 *transvalues;
3253 float8 N,
3254 Sxx;
3255
3256 transvalues = check_float8_array(transarray, "float8_var_samp", 3);
3257 N = transvalues[0];
3258 /* ignore Sx */
3259 Sxx = transvalues[2];
3260
3261 /* Sample variance is undefined when N is 0 or 1, so return NULL */
3262 if (N <= 1.0)
3264
3265 /* Note that Sxx is guaranteed to be non-negative */
3266
3267 PG_RETURN_FLOAT8(Sxx / (N - 1.0));
3268}
3269
3270Datum
3272{
3273 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3274 float8 *transvalues;
3275 float8 N,
3276 Sxx;
3277
3278 transvalues = check_float8_array(transarray, "float8_stddev_pop", 3);
3279 N = transvalues[0];
3280 /* ignore Sx */
3281 Sxx = transvalues[2];
3282
3283 /* Population stddev is undefined when N is 0, so return NULL */
3284 if (N == 0.0)
3286
3287 /* Note that Sxx is guaranteed to be non-negative */
3288
3289 PG_RETURN_FLOAT8(sqrt(Sxx / N));
3290}
3291
3292Datum
3294{
3295 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3296 float8 *transvalues;
3297 float8 N,
3298 Sxx;
3299
3300 transvalues = check_float8_array(transarray, "float8_stddev_samp", 3);
3301 N = transvalues[0];
3302 /* ignore Sx */
3303 Sxx = transvalues[2];
3304
3305 /* Sample stddev is undefined when N is 0 or 1, so return NULL */
3306 if (N <= 1.0)
3308
3309 /* Note that Sxx is guaranteed to be non-negative */
3310
3311 PG_RETURN_FLOAT8(sqrt(Sxx / (N - 1.0)));
3312}
3313
3314/*
3315 * =========================
3316 * SQL2003 BINARY AGGREGATES
3317 * =========================
3318 *
3319 * As with the preceding aggregates, we use the Youngs-Cramer algorithm to
3320 * reduce rounding errors in the aggregate final functions.
3321 *
3322 * The transition datatype for all these aggregates is a 6-element array of
3323 * float8, holding the values N, Sx=sum(X), Sxx=sum((X-Sx/N)^2), Sy=sum(Y),
3324 * Syy=sum((Y-Sy/N)^2), Sxy=sum((X-Sx/N)*(Y-Sy/N)) in that order.
3325 *
3326 * Note that Y is the first argument to all these aggregates!
3327 *
3328 * It might seem attractive to optimize this by having multiple accumulator
3329 * functions that only calculate the sums actually needed. But on most
3330 * modern machines, a couple of extra floating-point multiplies will be
3331 * insignificant compared to the other per-tuple overhead, so I've chosen
3332 * to minimize code space instead.
3333 */
3334
3335Datum
3337{
3338 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3339 float8 newvalY = PG_GETARG_FLOAT8(1);
3340 float8 newvalX = PG_GETARG_FLOAT8(2);
3341 float8 *transvalues;
3342 float8 N,
3343 Sx,
3344 Sxx,
3345 Sy,
3346 Syy,
3347 Sxy,
3348 tmpX,
3349 tmpY,
3350 scale;
3351
3352 transvalues = check_float8_array(transarray, "float8_regr_accum", 6);
3353 N = transvalues[0];
3354 Sx = transvalues[1];
3355 Sxx = transvalues[2];
3356 Sy = transvalues[3];
3357 Syy = transvalues[4];
3358 Sxy = transvalues[5];
3359
3360 /*
3361 * Use the Youngs-Cramer algorithm to incorporate the new values into the
3362 * transition values.
3363 */
3364 N += 1.0;
3365 Sx += newvalX;
3366 Sy += newvalY;
3367 if (transvalues[0] > 0.0)
3368 {
3369 tmpX = newvalX * N - Sx;
3370 tmpY = newvalY * N - Sy;
3371 scale = 1.0 / (N * transvalues[0]);
3372 Sxx += tmpX * tmpX * scale;
3373 Syy += tmpY * tmpY * scale;
3374 Sxy += tmpX * tmpY * scale;
3375
3376 /*
3377 * Overflow check. We only report an overflow error when finite
3378 * inputs lead to infinite results. Note also that Sxx, Syy and Sxy
3379 * should be NaN if any of the relevant inputs are infinite, so we
3380 * intentionally prevent them from becoming infinite.
3381 */
3382 if (isinf(Sx) || isinf(Sxx) || isinf(Sy) || isinf(Syy) || isinf(Sxy))
3383 {
3384 if (((isinf(Sx) || isinf(Sxx)) &&
3385 !isinf(transvalues[1]) && !isinf(newvalX)) ||
3386 ((isinf(Sy) || isinf(Syy)) &&
3387 !isinf(transvalues[3]) && !isinf(newvalY)) ||
3388 (isinf(Sxy) &&
3389 !isinf(transvalues[1]) && !isinf(newvalX) &&
3390 !isinf(transvalues[3]) && !isinf(newvalY)))
3392
3393 if (isinf(Sxx))
3394 Sxx = get_float8_nan();
3395 if (isinf(Syy))
3396 Syy = get_float8_nan();
3397 if (isinf(Sxy))
3398 Sxy = get_float8_nan();
3399 }
3400 }
3401 else
3402 {
3403 /*
3404 * At the first input, we normally can leave Sxx et al as 0. However,
3405 * if the first input is Inf or NaN, we'd better force the dependent
3406 * sums to NaN; otherwise we will falsely report variance zero when
3407 * there are no more inputs.
3408 */
3409 if (isnan(newvalX) || isinf(newvalX))
3410 Sxx = Sxy = get_float8_nan();
3411 if (isnan(newvalY) || isinf(newvalY))
3412 Syy = Sxy = get_float8_nan();
3413 }
3414
3415 /*
3416 * If we're invoked as an aggregate, we can cheat and modify our first
3417 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3418 * new array with the updated transition data and return it.
3419 */
3420 if (AggCheckCallContext(fcinfo, NULL))
3421 {
3422 transvalues[0] = N;
3423 transvalues[1] = Sx;
3424 transvalues[2] = Sxx;
3425 transvalues[3] = Sy;
3426 transvalues[4] = Syy;
3427 transvalues[5] = Sxy;
3428
3429 PG_RETURN_ARRAYTYPE_P(transarray);
3430 }
3431 else
3432 {
3433 Datum transdatums[6];
3434 ArrayType *result;
3435
3436 transdatums[0] = Float8GetDatumFast(N);
3437 transdatums[1] = Float8GetDatumFast(Sx);
3438 transdatums[2] = Float8GetDatumFast(Sxx);
3439 transdatums[3] = Float8GetDatumFast(Sy);
3440 transdatums[4] = Float8GetDatumFast(Syy);
3441 transdatums[5] = Float8GetDatumFast(Sxy);
3442
3443 result = construct_array_builtin(transdatums, 6, FLOAT8OID);
3444
3445 PG_RETURN_ARRAYTYPE_P(result);
3446 }
3447}
3448
3449/*
3450 * float8_regr_combine
3451 *
3452 * An aggregate combine function used to combine two 6 fields
3453 * aggregate transition data into a single transition data.
3454 * This function is used only in two stage aggregation and
3455 * shouldn't be called outside aggregate context.
3456 */
3457Datum
3459{
3460 ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
3461 ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
3462 float8 *transvalues1;
3463 float8 *transvalues2;
3464 float8 N1,
3465 Sx1,
3466 Sxx1,
3467 Sy1,
3468 Syy1,
3469 Sxy1,
3470 N2,
3471 Sx2,
3472 Sxx2,
3473 Sy2,
3474 Syy2,
3475 Sxy2,
3476 tmp1,
3477 tmp2,
3478 N,
3479 Sx,
3480 Sxx,
3481 Sy,
3482 Syy,
3483 Sxy;
3484
3485 transvalues1 = check_float8_array(transarray1, "float8_regr_combine", 6);
3486 transvalues2 = check_float8_array(transarray2, "float8_regr_combine", 6);
3487
3488 N1 = transvalues1[0];
3489 Sx1 = transvalues1[1];
3490 Sxx1 = transvalues1[2];
3491 Sy1 = transvalues1[3];
3492 Syy1 = transvalues1[4];
3493 Sxy1 = transvalues1[5];
3494
3495 N2 = transvalues2[0];
3496 Sx2 = transvalues2[1];
3497 Sxx2 = transvalues2[2];
3498 Sy2 = transvalues2[3];
3499 Syy2 = transvalues2[4];
3500 Sxy2 = transvalues2[5];
3501
3502 /*--------------------
3503 * The transition values combine using a generalization of the
3504 * Youngs-Cramer algorithm as follows:
3505 *
3506 * N = N1 + N2
3507 * Sx = Sx1 + Sx2
3508 * Sxx = Sxx1 + Sxx2 + N1 * N2 * (Sx1/N1 - Sx2/N2)^2 / N
3509 * Sy = Sy1 + Sy2
3510 * Syy = Syy1 + Syy2 + N1 * N2 * (Sy1/N1 - Sy2/N2)^2 / N
3511 * Sxy = Sxy1 + Sxy2 + N1 * N2 * (Sx1/N1 - Sx2/N2) * (Sy1/N1 - Sy2/N2) / N
3512 *
3513 * It's worth handling the special cases N1 = 0 and N2 = 0 separately
3514 * since those cases are trivial, and we then don't need to worry about
3515 * division-by-zero errors in the general case.
3516 *--------------------
3517 */
3518 if (N1 == 0.0)
3519 {
3520 N = N2;
3521 Sx = Sx2;
3522 Sxx = Sxx2;
3523 Sy = Sy2;
3524 Syy = Syy2;
3525 Sxy = Sxy2;
3526 }
3527 else if (N2 == 0.0)
3528 {
3529 N = N1;
3530 Sx = Sx1;
3531 Sxx = Sxx1;
3532 Sy = Sy1;
3533 Syy = Syy1;
3534 Sxy = Sxy1;
3535 }
3536 else
3537 {
3538 N = N1 + N2;
3539 Sx = float8_pl(Sx1, Sx2);
3540 tmp1 = Sx1 / N1 - Sx2 / N2;
3541 Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp1 * tmp1 / N;
3542 if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
3544 Sy = float8_pl(Sy1, Sy2);
3545 tmp2 = Sy1 / N1 - Sy2 / N2;
3546 Syy = Syy1 + Syy2 + N1 * N2 * tmp2 * tmp2 / N;
3547 if (unlikely(isinf(Syy)) && !isinf(Syy1) && !isinf(Syy2))
3549 Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N;
3550 if (unlikely(isinf(Sxy)) && !isinf(Sxy1) && !isinf(Sxy2))
3552 }
3553
3554 /*
3555 * If we're invoked as an aggregate, we can cheat and modify our first
3556 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3557 * new array with the updated transition data and return it.
3558 */
3559 if (AggCheckCallContext(fcinfo, NULL))
3560 {
3561 transvalues1[0] = N;
3562 transvalues1[1] = Sx;
3563 transvalues1[2] = Sxx;
3564 transvalues1[3] = Sy;
3565 transvalues1[4] = Syy;
3566 transvalues1[5] = Sxy;
3567
3568 PG_RETURN_ARRAYTYPE_P(transarray1);
3569 }
3570 else
3571 {
3572 Datum transdatums[6];
3573 ArrayType *result;
3574
3575 transdatums[0] = Float8GetDatumFast(N);
3576 transdatums[1] = Float8GetDatumFast(Sx);
3577 transdatums[2] = Float8GetDatumFast(Sxx);
3578 transdatums[3] = Float8GetDatumFast(Sy);
3579 transdatums[4] = Float8GetDatumFast(Syy);
3580 transdatums[5] = Float8GetDatumFast(Sxy);
3581
3582 result = construct_array_builtin(transdatums, 6, FLOAT8OID);
3583
3584 PG_RETURN_ARRAYTYPE_P(result);
3585 }
3586}
3587
3588
3589Datum
3591{
3592 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3593 float8 *transvalues;
3594 float8 N,
3595 Sxx;
3596
3597 transvalues = check_float8_array(transarray, "float8_regr_sxx", 6);
3598 N = transvalues[0];
3599 Sxx = transvalues[2];
3600
3601 /* if N is 0 we should return NULL */
3602 if (N < 1.0)
3604
3605 /* Note that Sxx is guaranteed to be non-negative */
3606
3607 PG_RETURN_FLOAT8(Sxx);
3608}
3609
3610Datum
3612{
3613 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3614 float8 *transvalues;
3615 float8 N,
3616 Syy;
3617
3618 transvalues = check_float8_array(transarray, "float8_regr_syy", 6);
3619 N = transvalues[0];
3620 Syy = transvalues[4];
3621
3622 /* if N is 0 we should return NULL */
3623 if (N < 1.0)
3625
3626 /* Note that Syy is guaranteed to be non-negative */
3627
3628 PG_RETURN_FLOAT8(Syy);
3629}
3630
3631Datum
3633{
3634 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3635 float8 *transvalues;
3636 float8 N,
3637 Sxy;
3638
3639 transvalues = check_float8_array(transarray, "float8_regr_sxy", 6);
3640 N = transvalues[0];
3641 Sxy = transvalues[5];
3642
3643 /* if N is 0 we should return NULL */
3644 if (N < 1.0)
3646
3647 /* A negative result is valid here */
3648
3649 PG_RETURN_FLOAT8(Sxy);
3650}
3651
3652Datum
3654{
3655 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3656 float8 *transvalues;
3657 float8 N,
3658 Sx;
3659
3660 transvalues = check_float8_array(transarray, "float8_regr_avgx", 6);
3661 N = transvalues[0];
3662 Sx = transvalues[1];
3663
3664 /* if N is 0 we should return NULL */
3665 if (N < 1.0)
3667
3668 PG_RETURN_FLOAT8(Sx / N);
3669}
3670
3671Datum
3673{
3674 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3675 float8 *transvalues;
3676 float8 N,
3677 Sy;
3678
3679 transvalues = check_float8_array(transarray, "float8_regr_avgy", 6);
3680 N = transvalues[0];
3681 Sy = transvalues[3];
3682
3683 /* if N is 0 we should return NULL */
3684 if (N < 1.0)
3686
3687 PG_RETURN_FLOAT8(Sy / N);
3688}
3689
3690Datum
3692{
3693 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3694 float8 *transvalues;
3695 float8 N,
3696 Sxy;
3697
3698 transvalues = check_float8_array(transarray, "float8_covar_pop", 6);
3699 N = transvalues[0];
3700 Sxy = transvalues[5];
3701
3702 /* if N is 0 we should return NULL */
3703 if (N < 1.0)
3705
3706 PG_RETURN_FLOAT8(Sxy / N);
3707}
3708
3709Datum
3711{
3712 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3713 float8 *transvalues;
3714 float8 N,
3715 Sxy;
3716
3717 transvalues = check_float8_array(transarray, "float8_covar_samp", 6);
3718 N = transvalues[0];
3719 Sxy = transvalues[5];
3720
3721 /* if N is <= 1 we should return NULL */
3722 if (N < 2.0)
3724
3725 PG_RETURN_FLOAT8(Sxy / (N - 1.0));
3726}
3727
3728Datum
3730{
3731 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3732 float8 *transvalues;
3733 float8 N,
3734 Sxx,
3735 Syy,
3736 Sxy;
3737
3738 transvalues = check_float8_array(transarray, "float8_corr", 6);
3739 N = transvalues[0];
3740 Sxx = transvalues[2];
3741 Syy = transvalues[4];
3742 Sxy = transvalues[5];
3743
3744 /* if N is 0 we should return NULL */
3745 if (N < 1.0)
3747
3748 /* Note that Sxx and Syy are guaranteed to be non-negative */
3749
3750 /* per spec, return NULL for horizontal and vertical lines */
3751 if (Sxx == 0 || Syy == 0)
3753
3754 PG_RETURN_FLOAT8(Sxy / sqrt(Sxx * Syy));
3755}
3756
3757Datum
3759{
3760 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3761 float8 *transvalues;
3762 float8 N,
3763 Sxx,
3764 Syy,
3765 Sxy;
3766
3767 transvalues = check_float8_array(transarray, "float8_regr_r2", 6);
3768 N = transvalues[0];
3769 Sxx = transvalues[2];
3770 Syy = transvalues[4];
3771 Sxy = transvalues[5];
3772
3773 /* if N is 0 we should return NULL */
3774 if (N < 1.0)
3776
3777 /* Note that Sxx and Syy are guaranteed to be non-negative */
3778
3779 /* per spec, return NULL for a vertical line */
3780 if (Sxx == 0)
3782
3783 /* per spec, return 1.0 for a horizontal line */
3784 if (Syy == 0)
3785 PG_RETURN_FLOAT8(1.0);
3786
3787 PG_RETURN_FLOAT8((Sxy * Sxy) / (Sxx * Syy));
3788}
3789
3790Datum
3792{
3793 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3794 float8 *transvalues;
3795 float8 N,
3796 Sxx,
3797 Sxy;
3798
3799 transvalues = check_float8_array(transarray, "float8_regr_slope", 6);
3800 N = transvalues[0];
3801 Sxx = transvalues[2];
3802 Sxy = transvalues[5];
3803
3804 /* if N is 0 we should return NULL */
3805 if (N < 1.0)
3807
3808 /* Note that Sxx is guaranteed to be non-negative */
3809
3810 /* per spec, return NULL for a vertical line */
3811 if (Sxx == 0)
3813
3814 PG_RETURN_FLOAT8(Sxy / Sxx);
3815}
3816
3817Datum
3819{
3820 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3821 float8 *transvalues;
3822 float8 N,
3823 Sx,
3824 Sxx,
3825 Sy,
3826 Sxy;
3827
3828 transvalues = check_float8_array(transarray, "float8_regr_intercept", 6);
3829 N = transvalues[0];
3830 Sx = transvalues[1];
3831 Sxx = transvalues[2];
3832 Sy = transvalues[3];
3833 Sxy = transvalues[5];
3834
3835 /* if N is 0 we should return NULL */
3836 if (N < 1.0)
3838
3839 /* Note that Sxx is guaranteed to be non-negative */
3840
3841 /* per spec, return NULL for a vertical line */
3842 if (Sxx == 0)
3844
3845 PG_RETURN_FLOAT8((Sy - Sx * Sxy / Sxx) / N);
3846}
3847
3848
3849/*
3850 * ====================================
3851 * MIXED-PRECISION ARITHMETIC OPERATORS
3852 * ====================================
3853 */
3854
3855/*
3856 * float48pl - returns arg1 + arg2
3857 * float48mi - returns arg1 - arg2
3858 * float48mul - returns arg1 * arg2
3859 * float48div - returns arg1 / arg2
3860 */
3861Datum
3863{
3864 float4 arg1 = PG_GETARG_FLOAT4(0);
3865 float8 arg2 = PG_GETARG_FLOAT8(1);
3866
3867 PG_RETURN_FLOAT8(float8_pl((float8) arg1, arg2));
3868}
3869
3870Datum
3872{
3873 float4 arg1 = PG_GETARG_FLOAT4(0);
3874 float8 arg2 = PG_GETARG_FLOAT8(1);
3875
3876 PG_RETURN_FLOAT8(float8_mi((float8) arg1, arg2));
3877}
3878
3879Datum
3881{
3882 float4 arg1 = PG_GETARG_FLOAT4(0);
3883 float8 arg2 = PG_GETARG_FLOAT8(1);
3884
3885 PG_RETURN_FLOAT8(float8_mul((float8) arg1, arg2));
3886}
3887
3888Datum
3890{
3891 float4 arg1 = PG_GETARG_FLOAT4(0);
3892 float8 arg2 = PG_GETARG_FLOAT8(1);
3893
3894 PG_RETURN_FLOAT8(float8_div((float8) arg1, arg2));
3895}
3896
3897/*
3898 * float84pl - returns arg1 + arg2
3899 * float84mi - returns arg1 - arg2
3900 * float84mul - returns arg1 * arg2
3901 * float84div - returns arg1 / arg2
3902 */
3903Datum
3905{
3906 float8 arg1 = PG_GETARG_FLOAT8(0);
3907 float4 arg2 = PG_GETARG_FLOAT4(1);
3908
3909 PG_RETURN_FLOAT8(float8_pl(arg1, (float8) arg2));
3910}
3911
3912Datum
3914{
3915 float8 arg1 = PG_GETARG_FLOAT8(0);
3916 float4 arg2 = PG_GETARG_FLOAT4(1);
3917
3918 PG_RETURN_FLOAT8(float8_mi(arg1, (float8) arg2));
3919}
3920
3921Datum
3923{
3924 float8 arg1 = PG_GETARG_FLOAT8(0);
3925 float4 arg2 = PG_GETARG_FLOAT4(1);
3926
3927 PG_RETURN_FLOAT8(float8_mul(arg1, (float8) arg2));
3928}
3929
3930Datum
3932{
3933 float8 arg1 = PG_GETARG_FLOAT8(0);
3934 float4 arg2 = PG_GETARG_FLOAT4(1);
3935
3936 PG_RETURN_FLOAT8(float8_div(arg1, (float8) arg2));
3937}
3938
3939/*
3940 * ====================
3941 * COMPARISON OPERATORS
3942 * ====================
3943 */
3944
3945/*
3946 * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
3947 */
3948Datum
3950{
3951 float4 arg1 = PG_GETARG_FLOAT4(0);
3952 float8 arg2 = PG_GETARG_FLOAT8(1);
3953
3954 PG_RETURN_BOOL(float8_eq((float8) arg1, arg2));
3955}
3956
3957Datum
3959{
3960 float4 arg1 = PG_GETARG_FLOAT4(0);
3961 float8 arg2 = PG_GETARG_FLOAT8(1);
3962
3963 PG_RETURN_BOOL(float8_ne((float8) arg1, arg2));
3964}
3965
3966Datum
3968{
3969 float4 arg1 = PG_GETARG_FLOAT4(0);
3970 float8 arg2 = PG_GETARG_FLOAT8(1);
3971
3972 PG_RETURN_BOOL(float8_lt((float8) arg1, arg2));
3973}
3974
3975Datum
3977{
3978 float4 arg1 = PG_GETARG_FLOAT4(0);
3979 float8 arg2 = PG_GETARG_FLOAT8(1);
3980
3981 PG_RETURN_BOOL(float8_le((float8) arg1, arg2));
3982}
3983
3984Datum
3986{
3987 float4 arg1 = PG_GETARG_FLOAT4(0);
3988 float8 arg2 = PG_GETARG_FLOAT8(1);
3989
3990 PG_RETURN_BOOL(float8_gt((float8) arg1, arg2));
3991}
3992
3993Datum
3995{
3996 float4 arg1 = PG_GETARG_FLOAT4(0);
3997 float8 arg2 = PG_GETARG_FLOAT8(1);
3998
3999 PG_RETURN_BOOL(float8_ge((float8) arg1, arg2));
4000}
4001
4002/*
4003 * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
4004 */
4005Datum
4007{
4008 float8 arg1 = PG_GETARG_FLOAT8(0);
4009 float4 arg2 = PG_GETARG_FLOAT4(1);
4010
4011 PG_RETURN_BOOL(float8_eq(arg1, (float8) arg2));
4012}
4013
4014Datum
4016{
4017 float8 arg1 = PG_GETARG_FLOAT8(0);
4018 float4 arg2 = PG_GETARG_FLOAT4(1);
4019
4020 PG_RETURN_BOOL(float8_ne(arg1, (float8) arg2));
4021}
4022
4023Datum
4025{
4026 float8 arg1 = PG_GETARG_FLOAT8(0);
4027 float4 arg2 = PG_GETARG_FLOAT4(1);
4028
4029 PG_RETURN_BOOL(float8_lt(arg1, (float8) arg2));
4030}
4031
4032Datum
4034{
4035 float8 arg1 = PG_GETARG_FLOAT8(0);
4036 float4 arg2 = PG_GETARG_FLOAT4(1);
4037
4038 PG_RETURN_BOOL(float8_le(arg1, (float8) arg2));
4039}
4040
4041Datum
4043{
4044 float8 arg1 = PG_GETARG_FLOAT8(0);
4045 float4 arg2 = PG_GETARG_FLOAT4(1);
4046
4047 PG_RETURN_BOOL(float8_gt(arg1, (float8) arg2));
4048}
4049
4050Datum
4052{
4053 float8 arg1 = PG_GETARG_FLOAT8(0);
4054 float4 arg2 = PG_GETARG_FLOAT4(1);
4055
4056 PG_RETURN_BOOL(float8_ge(arg1, (float8) arg2));
4057}
4058
4059/*
4060 * Implements the float8 version of the width_bucket() function
4061 * defined by SQL2003. See also width_bucket_numeric().
4062 *
4063 * 'bound1' and 'bound2' are the lower and upper bounds of the
4064 * histogram's range, respectively. 'count' is the number of buckets
4065 * in the histogram. width_bucket() returns an integer indicating the
4066 * bucket number that 'operand' belongs to in an equiwidth histogram
4067 * with the specified characteristics. An operand smaller than the
4068 * lower bound is assigned to bucket 0. An operand greater than the
4069 * upper bound is assigned to an additional bucket (with number
4070 * count+1). We don't allow "NaN" for any of the float8 inputs, and we
4071 * don't allow either of the histogram bounds to be +/- infinity.
4072 */
4073Datum
4075{
4076 float8 operand = PG_GETARG_FLOAT8(0);
4077 float8 bound1 = PG_GETARG_FLOAT8(1);
4078 float8 bound2 = PG_GETARG_FLOAT8(2);
4079 int32 count = PG_GETARG_INT32(3);
4080 int32 result;
4081
4082 if (count <= 0)
4083 ereport(ERROR,
4084 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4085 errmsg("count must be greater than zero")));
4086
4087 if (isnan(operand) || isnan(bound1) || isnan(bound2))
4088 ereport(ERROR,
4089 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4090 errmsg("operand, lower bound, and upper bound cannot be NaN")));
4091
4092 /* Note that we allow "operand" to be infinite */
4093 if (isinf(bound1) || isinf(bound2))
4094 ereport(ERROR,
4095 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4096 errmsg("lower and upper bounds must be finite")));
4097
4098 if (bound1 < bound2)
4099 {
4100 if (operand < bound1)
4101 result = 0;
4102 else if (operand >= bound2)
4103 {
4104 if (pg_add_s32_overflow(count, 1, &result))
4105 ereport(ERROR,
4106 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4107 errmsg("integer out of range")));
4108 }
4109 else
4110 {
4111 if (!isinf(bound2 - bound1))
4112 {
4113 /* The quotient is surely in [0,1], so this can't overflow */
4114 result = count * ((operand - bound1) / (bound2 - bound1));
4115 }
4116 else
4117 {
4118 /*
4119 * We get here if bound2 - bound1 overflows DBL_MAX. Since
4120 * both bounds are finite, their difference can't exceed twice
4121 * DBL_MAX; so we can perform the computation without overflow
4122 * by dividing all the inputs by 2. That should be exact too,
4123 * except in the case where a very small operand underflows to
4124 * zero, which would have negligible impact on the result
4125 * given such large bounds.
4126 */
4127 result = count * ((operand / 2 - bound1 / 2) / (bound2 / 2 - bound1 / 2));
4128 }
4129 /* The quotient could round to 1.0, which would be a lie */
4130 if (result >= count)
4131 result = count - 1;
4132 /* Having done that, we can add 1 without fear of overflow */
4133 result++;
4134 }
4135 }
4136 else if (bound1 > bound2)
4137 {
4138 if (operand > bound1)
4139 result = 0;
4140 else if (operand <= bound2)
4141 {
4142 if (pg_add_s32_overflow(count, 1, &result))
4143 ereport(ERROR,
4144 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4145 errmsg("integer out of range")));
4146 }
4147 else
4148 {
4149 if (!isinf(bound1 - bound2))
4150 result = count * ((bound1 - operand) / (bound1 - bound2));
4151 else
4152 result = count * ((bound1 / 2 - operand / 2) / (bound1 / 2 - bound2 / 2));
4153 if (result >= count)
4154 result = count - 1;
4155 result++;
4156 }
4157 }
4158 else
4159 {
4160 ereport(ERROR,
4161 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4162 errmsg("lower bound cannot equal upper bound")));
4163 result = 0; /* keep the compiler quiet */
4164 }
4165
4166 PG_RETURN_INT32(result);
4167}
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:265
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_HASNULL(a)
Definition: array.h:291
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
#define FLOAT4_FITS_IN_INT32(num)
Definition: c.h:1055
#define FLOAT8_FITS_IN_INT32(num)
Definition: c.h:1061
#define pg_noinline
Definition: c.h:286
#define FLOAT4_FITS_IN_INT16(num)
Definition: c.h:1053
double float8
Definition: c.h:601
int16_t int16
Definition: c.h:497
int32_t int32
Definition: c.h:498
#define FLOAT8_FITS_IN_INT16(num)
Definition: c.h:1059
#define unlikely(x)
Definition: c.h:347
float float4
Definition: c.h:600
int double_to_shortest_decimal_buf(double f, char *result)
Definition: d2s.c:1053
#define M_PI
Definition: earthdistance.c:11
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:149
int float_to_shortest_decimal_buf(float f, char *result)
Definition: f2s.c:780
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:395
Datum float4lt(PG_FUNCTION_ARGS)
Definition: float.c:844
Datum dceil(PG_FUNCTION_ARGS)
Definition: float.c:1380
Datum btfloat4cmp(PG_FUNCTION_ARGS)
Definition: float.c:880
float8 degree_c_sixty
Definition: float.c:68
static float8 acos_0_5
Definition: float.c:47
Datum float84gt(PG_FUNCTION_ARGS)
Definition: float.c:4042
Datum dasinh(PG_FUNCTION_ARGS)
Definition: float.c:2672
Datum float84mi(PG_FUNCTION_ARGS)
Definition: float.c:3913
static double sind_0_to_30(double x)
Definition: float.c:2252
Datum dtof(PG_FUNCTION_ARGS)
Definition: float.c:1195
Datum radians(PG_FUNCTION_ARGS)
Definition: float.c:2583
pg_noinline void float_zero_divide_error(void)
Definition: float.c:102
pg_noinline void float_overflow_error(void)
Definition: float.c:86
Datum width_bucket_float8(PG_FUNCTION_ARGS)
Definition: float.c:4074
Datum dasind(PG_FUNCTION_ARGS)
Definition: float.c:2145
Datum float8_var_samp(PG_FUNCTION_ARGS)
Definition: float.c:3249
Datum btfloat84cmp(PG_FUNCTION_ARGS)
Definition: float.c:1011
Datum ftoi4(PG_FUNCTION_ARGS)
Definition: float.c:1288
Datum dsind(PG_FUNCTION_ARGS)
Definition: float.c:2439
Datum datan2(PG_FUNCTION_ARGS)
Definition: float.c:1843
Datum derfc(PG_FUNCTION_ARGS)
Definition: float.c:2772
Datum float8div(PG_FUNCTION_ARGS)
Definition: float.c:797
Datum float8_regr_syy(PG_FUNCTION_ARGS)
Definition: float.c:3611
Datum float48gt(PG_FUNCTION_ARGS)
Definition: float.c:3985
Datum degrees(PG_FUNCTION_ARGS)
Definition: float.c:2561
Datum btfloat4sortsupport(PG_FUNCTION_ARGS)
Definition: float.c:898
Datum dlgamma(PG_FUNCTION_ARGS)
Definition: float.c:2850
Datum dacosd(PG_FUNCTION_ARGS)
Definition: float.c:2108
float8 degree_c_thirty
Definition: float.c:66
int extra_float_digits
Definition: float.c:40
static double acosd_q1(double x)
Definition: float.c:2081
Datum float8_regr_r2(PG_FUNCTION_ARGS)
Definition: float.c:3758
Datum float8_regr_combine(PG_FUNCTION_ARGS)
Definition: float.c:3458
Datum float8_regr_slope(PG_FUNCTION_ARGS)
Definition: float.c:3791
Datum float8eq(PG_FUNCTION_ARGS)
Definition: float.c:920
Datum dtanh(PG_FUNCTION_ARGS)
Definition: float.c:2652
static double cosd_q1(double x)
Definition: float.c:2299
Datum dlog10(PG_FUNCTION_ARGS)
Definition: float.c:1722
Datum float84mul(PG_FUNCTION_ARGS)
Definition: float.c:3922
static bool degree_consts_set
Definition: float.c:43
Datum datanh(PG_FUNCTION_ARGS)
Definition: float.c:2714
Datum dcosd(PG_FUNCTION_ARGS)
Definition: float.c:2318
static int btfloat8fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: float.c:983
Datum derf(PG_FUNCTION_ARGS)
Definition: float.c:2752
Datum float4up(PG_FUNCTION_ARGS)
Definition: float.c:612
static float8 atan_1_0
Definition: float.c:48
Datum float48pl(PG_FUNCTION_ARGS)
Definition: float.c:3862
Datum dsinh(PG_FUNCTION_ARGS)
Definition: float.c:2598
Datum float8_combine(PG_FUNCTION_ARGS)
Definition: float.c:2951
Datum float8_avg(PG_FUNCTION_ARGS)
Definition: float.c:3207
Datum float8_covar_pop(PG_FUNCTION_ARGS)
Definition: float.c:3691
Datum dtan(PG_FUNCTION_ARGS)
Definition: float.c:1965
Datum float8ge(PG_FUNCTION_ARGS)
Definition: float.c:965
Datum float8_stddev_pop(PG_FUNCTION_ARGS)
Definition: float.c:3271
static double asind_q1(double x)
Definition: float.c:2048
Datum dround(PG_FUNCTION_ARGS)
Definition: float.c:1368
Datum float4um(PG_FUNCTION_ARGS)
Definition: float.c:602
Datum dlog1(PG_FUNCTION_ARGS)
Definition: float.c:1690
Datum datan2d(PG_FUNCTION_ARGS)
Definition: float.c:2214
Datum float4abs(PG_FUNCTION_ARGS)
Definition: float.c:591
Datum ftod(PG_FUNCTION_ARGS)
Definition: float.c:1183
Datum float4mul(PG_FUNCTION_ARGS)
Definition: float.c:746
Datum float4le(PG_FUNCTION_ARGS)
Definition: float.c:853
Datum dcos(PG_FUNCTION_ARGS)
Definition: float.c:1869
Datum float8_regr_intercept(PG_FUNCTION_ARGS)
Definition: float.c:3818
Datum float8out(PG_FUNCTION_ARGS)
Definition: float.c:522
Datum float84le(PG_FUNCTION_ARGS)
Definition: float.c:4033
Datum dexp(PG_FUNCTION_ARGS)
Definition: float.c:1644
Datum float8pl(PG_FUNCTION_ARGS)
Definition: float.c:770
Datum float8lt(PG_FUNCTION_ARGS)
Definition: float.c:938
Datum float4gt(PG_FUNCTION_ARGS)
Definition: float.c:862
Datum float4out(PG_FUNCTION_ARGS)
Definition: float.c:319
#define INIT_DEGREE_CONSTANTS()
Definition: float.c:2031
Datum dsign(PG_FUNCTION_ARGS)
Definition: float.c:1405
Datum float8recv(PG_FUNCTION_ARGS)
Definition: float.c:556
Datum float4send(PG_FUNCTION_ARGS)
Definition: float.c:350
static float8 cot_45
Definition: float.c:50
Datum float4ne(PG_FUNCTION_ARGS)
Definition: float.c:835
Datum float84eq(PG_FUNCTION_ARGS)
Definition: float.c:4006
Datum float84lt(PG_FUNCTION_ARGS)
Definition: float.c:4024
Datum float48mi(PG_FUNCTION_ARGS)
Definition: float.c:3871
Datum float8le(PG_FUNCTION_ARGS)
Definition: float.c:947
Datum dtrunc(PG_FUNCTION_ARGS)
Definition: float.c:1428
Datum btfloat8cmp(PG_FUNCTION_ARGS)
Definition: float.c:974
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:364
Datum float8ne(PG_FUNCTION_ARGS)
Definition: float.c:929
Datum dpow(PG_FUNCTION_ARGS)
Definition: float.c:1489
Datum float8mi(PG_FUNCTION_ARGS)
Definition: float.c:779
static double sind_q1(double x)
Definition: float.c:2279
Datum ftoi2(PG_FUNCTION_ARGS)
Definition: float.c:1313
Datum float4mi(PG_FUNCTION_ARGS)
Definition: float.c:737
Datum float8_accum(PG_FUNCTION_ARGS)
Definition: float.c:3043
Datum float48eq(PG_FUNCTION_ARGS)
Definition: float.c:3949
Datum i2tof(PG_FUNCTION_ARGS)
Definition: float.c:1350
static float8 one_minus_cos_60
Definition: float.c:45
Datum float84pl(PG_FUNCTION_ARGS)
Definition: float.c:3904
Datum btfloat48cmp(PG_FUNCTION_ARGS)
Definition: float.c:1001
Datum float48ge(PG_FUNCTION_ARGS)
Definition: float.c:3994
Datum float84div(PG_FUNCTION_ARGS)
Definition: float.c:3931
Datum dcotd(PG_FUNCTION_ARGS)
Definition: float.c:2373
pg_noinline void float_underflow_error(void)
Definition: float.c:94
Datum float8smaller(PG_FUNCTION_ARGS)
Definition: float.c:701
float8 degree_c_forty_five
Definition: float.c:67
Datum dsqrt(PG_FUNCTION_ARGS)
Definition: float.c:1446
Datum float84ge(PG_FUNCTION_ARGS)
Definition: float.c:4051
Datum float8_stddev_samp(PG_FUNCTION_ARGS)
Definition: float.c:3293
Datum datand(PG_FUNCTION_ARGS)
Definition: float.c:2182
Datum float8larger(PG_FUNCTION_ARGS)
Definition: float.c:687
Datum dcbrt(PG_FUNCTION_ARGS)
Definition: float.c:1470
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:164
static int btfloat4fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: float.c:889
Datum float8_regr_sxy(PG_FUNCTION_ARGS)
Definition: float.c:3632
Datum float8_var_pop(PG_FUNCTION_ARGS)
Definition: float.c:3227
Datum float48div(PG_FUNCTION_ARGS)
Definition: float.c:3889
Datum float84ne(PG_FUNCTION_ARGS)
Definition: float.c:4015
Datum float4_accum(PG_FUNCTION_ARGS)
Definition: float.c:3124
Datum float8up(PG_FUNCTION_ARGS)
Definition: float.c:679
int float4_cmp_internal(float4 a, float4 b)
Definition: float.c:816
static float8 tan_45
Definition: float.c:49
Datum float48le(PG_FUNCTION_ARGS)
Definition: float.c:3976
Datum float8_regr_sxx(PG_FUNCTION_ARGS)
Definition: float.c:3590
Datum float8_corr(PG_FUNCTION_ARGS)
Definition: float.c:3729
static float8 sin_30
Definition: float.c:44
float8 degree_c_one
Definition: float.c:70
Datum float4recv(PG_FUNCTION_ARGS)
Definition: float.c:339
float8 degree_c_one_half
Definition: float.c:69
Datum in_range_float8_float8(PG_FUNCTION_ARGS)
Definition: float.c:1027
Datum float48ne(PG_FUNCTION_ARGS)
Definition: float.c:3958
Datum dpi(PG_FUNCTION_ARGS)
Definition: float.c:2573
float4 float4in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:183
Datum dacos(PG_FUNCTION_ARGS)
Definition: float.c:1755
Datum float48lt(PG_FUNCTION_ARGS)
Definition: float.c:3967
static void init_degree_constants(void)
Definition: float.c:2019
Datum dgamma(PG_FUNCTION_ARGS)
Definition: float.c:2796
Datum float8mul(PG_FUNCTION_ARGS)
Definition: float.c:788
Datum float4div(PG_FUNCTION_ARGS)
Definition: float.c:755
Datum in_range_float4_float8(PG_FUNCTION_ARGS)
Definition: float.c:1103
Datum dtand(PG_FUNCTION_ARGS)
Definition: float.c:2495
Datum float8abs(PG_FUNCTION_ARGS)
Definition: float.c:657
Datum i4tod(PG_FUNCTION_ARGS)
Definition: float.c:1264
int is_infinite(double val)
Definition: float.c:118
Datum i2tod(PG_FUNCTION_ARGS)
Definition: float.c:1276
Datum dfloor(PG_FUNCTION_ARGS)
Definition: float.c:1392
Datum btfloat8sortsupport(PG_FUNCTION_ARGS)
Definition: float.c:992
Datum dcosh(PG_FUNCTION_ARGS)
Definition: float.c:2627
Datum dacosh(PG_FUNCTION_ARGS)
Definition: float.c:2689
Datum float4ge(PG_FUNCTION_ARGS)
Definition: float.c:871
Datum dasin(PG_FUNCTION_ARGS)
Definition: float.c:1786
Datum i4tof(PG_FUNCTION_ARGS)
Definition: float.c:1338
Datum datan(PG_FUNCTION_ARGS)
Definition: float.c:1817
Datum float8gt(PG_FUNCTION_ARGS)
Definition: float.c:956
Datum float8_regr_avgx(PG_FUNCTION_ARGS)
Definition: float.c:3653
Datum float8um(PG_FUNCTION_ARGS)
Definition: float.c:669
Datum float8_regr_avgy(PG_FUNCTION_ARGS)
Definition: float.c:3672
Datum dcot(PG_FUNCTION_ARGS)
Definition: float.c:1910
Datum dsin(PG_FUNCTION_ARGS)
Definition: float.c:1938
Datum dtoi4(PG_FUNCTION_ARGS)
Definition: float.c:1214
Datum float4pl(PG_FUNCTION_ARGS)
Definition: float.c:728
static float8 asin_0_5
Definition: float.c:46
Datum float8_covar_samp(PG_FUNCTION_ARGS)
Definition: float.c:3710
Datum float8send(PG_FUNCTION_ARGS)
Definition: float.c:567
Datum float4larger(PG_FUNCTION_ARGS)
Definition: float.c:620
Datum dtoi2(PG_FUNCTION_ARGS)
Definition: float.c:1239
static float8 * check_float8_array(ArrayType *transarray, const char *caller, int n)
Definition: float.c:2927
static double cosd_0_to_60(double x)
Definition: float.c:2266
Datum float48mul(PG_FUNCTION_ARGS)
Definition: float.c:3880
Datum float4smaller(PG_FUNCTION_ARGS)
Definition: float.c:634
Datum float8_regr_accum(PG_FUNCTION_ARGS)
Definition: float.c:3336
char * float8out_internal(double num)
Definition: float.c:537
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:910
Datum float4eq(PG_FUNCTION_ARGS)
Definition: float.c:826
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:208
static float4 float4_div(const float4 val1, const float4 val2)
Definition: float.h:222
#define RADIANS_PER_DEGREE
Definition: float.h:26
static float4 get_float4_infinity(void)
Definition: float.h:74
static bool float4_lt(const float4 val1, const float4 val2)
Definition: float.h:286
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:158
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:182
static bool float4_ge(const float4 val1, const float4 val2)
Definition: float.h:322
static float4 get_float4_nan(void)
Definition: float.h:111
static bool float8_ne(const float8 val1, const float8 val2)
Definition: float.h:280
static bool float4_ne(const float4 val1, const float4 val2)
Definition: float.h:274
static float4 float4_pl(const float4 val1, const float4 val2)
Definition: float.h:146
static bool float4_eq(const float4 val1, const float4 val2)
Definition: float.h:262
static float4 float4_mul(const float4 val1, const float4 val2)
Definition: float.h:194
static float8 get_float8_infinity(void)
Definition: float.h:94
static bool float8_ge(const float8 val1, const float8 val2)
Definition: float.h:328
static float4 float4_mi(const float4 val1, const float4 val2)
Definition: float.h:170
static bool float8_le(const float8 val1, const float8 val2)
Definition: float.h:304
static bool float4_gt(const float4 val1, const float4 val2)
Definition: float.h:310
static bool float8_eq(const float8 val1, const float8 val2)
Definition: float.h:268
static bool float4_le(const float4 val1, const float4 val2)
Definition: float.h:298
static float8 get_float8_nan(void)
Definition: float.h:123
static float8 float8_div(const float8 val1, const float8 val2)
Definition: float.h:238
static bool float8_lt(const float8 val1, const float8 val2)
Definition: float.h:292
static bool float8_gt(const float8 val1, const float8 val2)
Definition: float.h:316
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_INT16(x)
Definition: fmgr.h:356
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_RETURN_FLOAT4(x)
Definition: fmgr.h:366
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
long val
Definition: informix.c:689
char sign
Definition: informix.c:693
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:151
int y
Definition: isn.c:76
int b
Definition: isn.c:74
int x
Definition: isn.c:75
int a
Definition: isn.c:73
char * pstrdup(const char *in)
Definition: mcxt.c:2322
void * palloc(Size size)
Definition: mcxt.c:1940
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4614
Datum ascii(PG_FUNCTION_ARGS)
void * arg
static char * buf
Definition: pg_test_fsync.c:72
static int scale
Definition: pgbench.c:182
int pg_strfromd(char *str, size_t count, int precision, double value)
Definition: snprintf.c:1318
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
uintptr_t Datum
Definition: postgres.h:69
static float4 DatumGetFloat4(Datum X)
Definition: postgres.h:463
#define Float8GetDatumFast(X)
Definition: postgres.h:561
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:499
float4 pq_getmsgfloat4(StringInfo msg)
Definition: pqformat.c:469
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:488
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
void pq_sendfloat4(StringInfo buf, float4 f)
Definition: pqformat.c:252
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
void pq_sendfloat8(StringInfo buf, float8 f)
Definition: pqformat.c:276
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
StringInfoData * StringInfo
Definition: stringinfo.h:54
Definition: nodes.h:135
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106