PostgreSQL Source Code git master
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 an 8-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)), commonX, and commonY
3325 * in that order.
3326 *
3327 * commonX is defined as the common X value if all the X values were the same,
3328 * else NaN; likewise for commonY. This is useful for deciding whether corr()
3329 * and related functions should return NULL. This representation cannot
3330 * distinguish the-values-were-all-NaN from the-values-were-not-all-the-same,
3331 * but that's okay because for this purpose we use the IEEE float arithmetic
3332 * principle that two NaNs are never equal. The SQL standard doesn't mention
3333 * NaNs, but it says that NULL is to be returned when N*sum(X*X) equals
3334 * sum(X)*sum(X) (etc), and that shouldn't be considered true for NaNs.
3335 * Testing this as written in the spec would be highly subject to roundoff
3336 * error, so instead we directly track whether all the inputs are equal.
3337 *
3338 * Note that Y is the first argument to all these aggregates!
3339 *
3340 * It might seem attractive to optimize this by having multiple accumulator
3341 * functions that only calculate the sums actually needed. But on most
3342 * modern machines, a couple of extra floating-point multiplies will be
3343 * insignificant compared to the other per-tuple overhead, so I've chosen
3344 * to minimize code space instead.
3345 */
3346
3347Datum
3349{
3350 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3351 float8 newvalY = PG_GETARG_FLOAT8(1);
3352 float8 newvalX = PG_GETARG_FLOAT8(2);
3353 float8 *transvalues;
3354 float8 N,
3355 Sx,
3356 Sxx,
3357 Sy,
3358 Syy,
3359 Sxy,
3360 commonX,
3361 commonY,
3362 tmpX,
3363 tmpY,
3364 scale;
3365
3366 transvalues = check_float8_array(transarray, "float8_regr_accum", 8);
3367 N = transvalues[0];
3368 Sx = transvalues[1];
3369 Sxx = transvalues[2];
3370 Sy = transvalues[3];
3371 Syy = transvalues[4];
3372 Sxy = transvalues[5];
3373 commonX = transvalues[6];
3374 commonY = transvalues[7];
3375
3376 /*
3377 * Use the Youngs-Cramer algorithm to incorporate the new values into the
3378 * transition values.
3379 */
3380 N += 1.0;
3381 Sx += newvalX;
3382 Sy += newvalY;
3383 if (transvalues[0] > 0.0)
3384 {
3385 /*
3386 * Check to see if we have seen distinct inputs. We can use a test
3387 * that's a bit cheaper than float8_ne() because if commonX is already
3388 * NaN, it does not matter whether the != test returns true or not.
3389 */
3390 if (newvalX != commonX || isnan(newvalX))
3391 commonX = get_float8_nan();
3392 if (newvalY != commonY || isnan(newvalY))
3393 commonY = get_float8_nan();
3394
3395 tmpX = newvalX * N - Sx;
3396 tmpY = newvalY * N - Sy;
3397 scale = 1.0 / (N * transvalues[0]);
3398
3399 /*
3400 * If we have not seen distinct inputs, then Sxx, Syy, and/or Sxy
3401 * should remain zero (since Sx's exact value would be N * commonX,
3402 * etc). Updating them would just create the possibility of injecting
3403 * roundoff error, and we need exact zero results so that the final
3404 * functions will return NULL in the right cases.
3405 */
3406 if (isnan(commonX))
3407 Sxx += tmpX * tmpX * scale;
3408 if (isnan(commonY))
3409 Syy += tmpY * tmpY * scale;
3410 if (isnan(commonX) && isnan(commonY))
3411 Sxy += tmpX * tmpY * scale;
3412
3413 /*
3414 * Overflow check. We only report an overflow error when finite
3415 * inputs lead to infinite results. Note also that Sxx, Syy and Sxy
3416 * should be NaN if any of the relevant inputs are infinite, so we
3417 * intentionally prevent them from becoming infinite.
3418 */
3419 if (isinf(Sx) || isinf(Sxx) || isinf(Sy) || isinf(Syy) || isinf(Sxy))
3420 {
3421 if (((isinf(Sx) || isinf(Sxx)) &&
3422 !isinf(transvalues[1]) && !isinf(newvalX)) ||
3423 ((isinf(Sy) || isinf(Syy)) &&
3424 !isinf(transvalues[3]) && !isinf(newvalY)) ||
3425 (isinf(Sxy) &&
3426 !isinf(transvalues[1]) && !isinf(newvalX) &&
3427 !isinf(transvalues[3]) && !isinf(newvalY)))
3429
3430 if (isinf(Sxx))
3431 Sxx = get_float8_nan();
3432 if (isinf(Syy))
3433 Syy = get_float8_nan();
3434 if (isinf(Sxy))
3435 Sxy = get_float8_nan();
3436 }
3437 }
3438 else
3439 {
3440 /*
3441 * At the first input, we normally can leave Sxx et al as 0. However,
3442 * if the first input is Inf or NaN, we'd better force the dependent
3443 * sums to NaN; otherwise we will falsely report variance zero when
3444 * there are no more inputs.
3445 */
3446 if (isnan(newvalX) || isinf(newvalX))
3447 Sxx = Sxy = get_float8_nan();
3448 if (isnan(newvalY) || isinf(newvalY))
3449 Syy = Sxy = get_float8_nan();
3450
3451 commonX = newvalX;
3452 commonY = newvalY;
3453 }
3454
3455 /*
3456 * If we're invoked as an aggregate, we can cheat and modify our first
3457 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3458 * new array with the updated transition data and return it.
3459 */
3460 if (AggCheckCallContext(fcinfo, NULL))
3461 {
3462 transvalues[0] = N;
3463 transvalues[1] = Sx;
3464 transvalues[2] = Sxx;
3465 transvalues[3] = Sy;
3466 transvalues[4] = Syy;
3467 transvalues[5] = Sxy;
3468 transvalues[6] = commonX;
3469 transvalues[7] = commonY;
3470
3471 PG_RETURN_ARRAYTYPE_P(transarray);
3472 }
3473 else
3474 {
3475 Datum transdatums[8];
3476 ArrayType *result;
3477
3478 transdatums[0] = Float8GetDatumFast(N);
3479 transdatums[1] = Float8GetDatumFast(Sx);
3480 transdatums[2] = Float8GetDatumFast(Sxx);
3481 transdatums[3] = Float8GetDatumFast(Sy);
3482 transdatums[4] = Float8GetDatumFast(Syy);
3483 transdatums[5] = Float8GetDatumFast(Sxy);
3484 transdatums[6] = Float8GetDatumFast(commonX);
3485 transdatums[7] = Float8GetDatumFast(commonY);
3486
3487 result = construct_array_builtin(transdatums, 8, FLOAT8OID);
3488
3489 PG_RETURN_ARRAYTYPE_P(result);
3490 }
3491}
3492
3493/*
3494 * float8_regr_combine
3495 *
3496 * An aggregate combine function used to combine two 8-fields
3497 * aggregate transition data into a single transition data.
3498 * This function is used only in two stage aggregation and
3499 * shouldn't be called outside aggregate context.
3500 */
3501Datum
3503{
3504 ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
3505 ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
3506 float8 *transvalues1;
3507 float8 *transvalues2;
3508 float8 N1,
3509 Sx1,
3510 Sxx1,
3511 Sy1,
3512 Syy1,
3513 Sxy1,
3514 Cx1,
3515 Cy1,
3516 N2,
3517 Sx2,
3518 Sxx2,
3519 Sy2,
3520 Syy2,
3521 Sxy2,
3522 Cx2,
3523 Cy2,
3524 tmp1,
3525 tmp2,
3526 N,
3527 Sx,
3528 Sxx,
3529 Sy,
3530 Syy,
3531 Sxy,
3532 Cx,
3533 Cy;
3534
3535 transvalues1 = check_float8_array(transarray1, "float8_regr_combine", 8);
3536 transvalues2 = check_float8_array(transarray2, "float8_regr_combine", 8);
3537
3538 N1 = transvalues1[0];
3539 Sx1 = transvalues1[1];
3540 Sxx1 = transvalues1[2];
3541 Sy1 = transvalues1[3];
3542 Syy1 = transvalues1[4];
3543 Sxy1 = transvalues1[5];
3544 Cx1 = transvalues1[6];
3545 Cy1 = transvalues1[7];
3546
3547 N2 = transvalues2[0];
3548 Sx2 = transvalues2[1];
3549 Sxx2 = transvalues2[2];
3550 Sy2 = transvalues2[3];
3551 Syy2 = transvalues2[4];
3552 Sxy2 = transvalues2[5];
3553 Cx2 = transvalues2[6];
3554 Cy2 = transvalues2[7];
3555
3556 /*--------------------
3557 * The transition values combine using a generalization of the
3558 * Youngs-Cramer algorithm as follows:
3559 *
3560 * N = N1 + N2
3561 * Sx = Sx1 + Sx2
3562 * Sxx = Sxx1 + Sxx2 + N1 * N2 * (Sx1/N1 - Sx2/N2)^2 / N
3563 * Sy = Sy1 + Sy2
3564 * Syy = Syy1 + Syy2 + N1 * N2 * (Sy1/N1 - Sy2/N2)^2 / N
3565 * Sxy = Sxy1 + Sxy2 + N1 * N2 * (Sx1/N1 - Sx2/N2) * (Sy1/N1 - Sy2/N2) / N
3566 *
3567 * It's worth handling the special cases N1 = 0 and N2 = 0 separately
3568 * since those cases are trivial, and we then don't need to worry about
3569 * division-by-zero errors in the general case.
3570 *--------------------
3571 */
3572 if (N1 == 0.0)
3573 {
3574 N = N2;
3575 Sx = Sx2;
3576 Sxx = Sxx2;
3577 Sy = Sy2;
3578 Syy = Syy2;
3579 Sxy = Sxy2;
3580 Cx = Cx2;
3581 Cy = Cy2;
3582 }
3583 else if (N2 == 0.0)
3584 {
3585 N = N1;
3586 Sx = Sx1;
3587 Sxx = Sxx1;
3588 Sy = Sy1;
3589 Syy = Syy1;
3590 Sxy = Sxy1;
3591 Cx = Cx1;
3592 Cy = Cy1;
3593 }
3594 else
3595 {
3596 N = N1 + N2;
3597 Sx = float8_pl(Sx1, Sx2);
3598 tmp1 = Sx1 / N1 - Sx2 / N2;
3599 Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp1 * tmp1 / N;
3600 if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
3602 Sy = float8_pl(Sy1, Sy2);
3603 tmp2 = Sy1 / N1 - Sy2 / N2;
3604 Syy = Syy1 + Syy2 + N1 * N2 * tmp2 * tmp2 / N;
3605 if (unlikely(isinf(Syy)) && !isinf(Syy1) && !isinf(Syy2))
3607 Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N;
3608 if (unlikely(isinf(Sxy)) && !isinf(Sxy1) && !isinf(Sxy2))
3610 if (float8_eq(Cx1, Cx2))
3611 Cx = Cx1;
3612 else
3613 Cx = get_float8_nan();
3614 if (float8_eq(Cy1, Cy2))
3615 Cy = Cy1;
3616 else
3617 Cy = get_float8_nan();
3618 }
3619
3620 /*
3621 * If we're invoked as an aggregate, we can cheat and modify our first
3622 * parameter in-place to reduce palloc overhead. Otherwise we construct a
3623 * new array with the updated transition data and return it.
3624 */
3625 if (AggCheckCallContext(fcinfo, NULL))
3626 {
3627 transvalues1[0] = N;
3628 transvalues1[1] = Sx;
3629 transvalues1[2] = Sxx;
3630 transvalues1[3] = Sy;
3631 transvalues1[4] = Syy;
3632 transvalues1[5] = Sxy;
3633 transvalues1[6] = Cx;
3634 transvalues1[7] = Cy;
3635
3636 PG_RETURN_ARRAYTYPE_P(transarray1);
3637 }
3638 else
3639 {
3640 Datum transdatums[8];
3641 ArrayType *result;
3642
3643 transdatums[0] = Float8GetDatumFast(N);
3644 transdatums[1] = Float8GetDatumFast(Sx);
3645 transdatums[2] = Float8GetDatumFast(Sxx);
3646 transdatums[3] = Float8GetDatumFast(Sy);
3647 transdatums[4] = Float8GetDatumFast(Syy);
3648 transdatums[5] = Float8GetDatumFast(Sxy);
3649 transdatums[6] = Float8GetDatumFast(Cx);
3650 transdatums[7] = Float8GetDatumFast(Cy);
3651
3652 result = construct_array_builtin(transdatums, 8, FLOAT8OID);
3653
3654 PG_RETURN_ARRAYTYPE_P(result);
3655 }
3656}
3657
3658
3659Datum
3661{
3662 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3663 float8 *transvalues;
3664 float8 N,
3665 Sxx;
3666
3667 transvalues = check_float8_array(transarray, "float8_regr_sxx", 8);
3668 N = transvalues[0];
3669 Sxx = transvalues[2];
3670
3671 /* if N is 0 we should return NULL */
3672 if (N < 1.0)
3674
3675 /* Note that Sxx is guaranteed to be non-negative */
3676
3677 PG_RETURN_FLOAT8(Sxx);
3678}
3679
3680Datum
3682{
3683 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3684 float8 *transvalues;
3685 float8 N,
3686 Syy;
3687
3688 transvalues = check_float8_array(transarray, "float8_regr_syy", 8);
3689 N = transvalues[0];
3690 Syy = transvalues[4];
3691
3692 /* if N is 0 we should return NULL */
3693 if (N < 1.0)
3695
3696 /* Note that Syy is guaranteed to be non-negative */
3697
3698 PG_RETURN_FLOAT8(Syy);
3699}
3700
3701Datum
3703{
3704 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3705 float8 *transvalues;
3706 float8 N,
3707 Sxy;
3708
3709 transvalues = check_float8_array(transarray, "float8_regr_sxy", 8);
3710 N = transvalues[0];
3711 Sxy = transvalues[5];
3712
3713 /* if N is 0 we should return NULL */
3714 if (N < 1.0)
3716
3717 /* A negative result is valid here */
3718
3719 PG_RETURN_FLOAT8(Sxy);
3720}
3721
3722Datum
3724{
3725 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3726 float8 *transvalues;
3727 float8 N,
3728 Sx,
3729 commonX;
3730
3731 transvalues = check_float8_array(transarray, "float8_regr_avgx", 8);
3732 N = transvalues[0];
3733 Sx = transvalues[1];
3734 commonX = transvalues[6];
3735
3736 /* if N is 0 we should return NULL */
3737 if (N < 1.0)
3739
3740 /* if all inputs were the same just return that, avoiding roundoff error */
3741 if (!isnan(commonX))
3742 PG_RETURN_FLOAT8(commonX);
3743
3744 PG_RETURN_FLOAT8(Sx / N);
3745}
3746
3747Datum
3749{
3750 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3751 float8 *transvalues;
3752 float8 N,
3753 Sy,
3754 commonY;
3755
3756 transvalues = check_float8_array(transarray, "float8_regr_avgy", 8);
3757 N = transvalues[0];
3758 Sy = transvalues[3];
3759 commonY = transvalues[7];
3760
3761 /* if N is 0 we should return NULL */
3762 if (N < 1.0)
3764
3765 /* if all inputs were the same just return that, avoiding roundoff error */
3766 if (!isnan(commonY))
3767 PG_RETURN_FLOAT8(commonY);
3768
3769 PG_RETURN_FLOAT8(Sy / N);
3770}
3771
3772Datum
3774{
3775 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3776 float8 *transvalues;
3777 float8 N,
3778 Sxy;
3779
3780 transvalues = check_float8_array(transarray, "float8_covar_pop", 8);
3781 N = transvalues[0];
3782 Sxy = transvalues[5];
3783
3784 /* if N is 0 we should return NULL */
3785 if (N < 1.0)
3787
3788 PG_RETURN_FLOAT8(Sxy / N);
3789}
3790
3791Datum
3793{
3794 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3795 float8 *transvalues;
3796 float8 N,
3797 Sxy;
3798
3799 transvalues = check_float8_array(transarray, "float8_covar_samp", 8);
3800 N = transvalues[0];
3801 Sxy = transvalues[5];
3802
3803 /* if N is <= 1 we should return NULL */
3804 if (N < 2.0)
3806
3807 PG_RETURN_FLOAT8(Sxy / (N - 1.0));
3808}
3809
3810Datum
3812{
3813 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3814 float8 *transvalues;
3815 float8 N,
3816 Sxx,
3817 Syy,
3818 Sxy,
3819 product,
3820 sqrtproduct,
3821 result;
3822
3823 transvalues = check_float8_array(transarray, "float8_corr", 8);
3824 N = transvalues[0];
3825 Sxx = transvalues[2];
3826 Syy = transvalues[4];
3827 Sxy = transvalues[5];
3828
3829 /* if N is 0 we should return NULL */
3830 if (N < 1.0)
3832
3833 /* Note that Sxx and Syy are guaranteed to be non-negative */
3834
3835 /* per spec, return NULL for horizontal and vertical lines */
3836 if (Sxx == 0 || Syy == 0)
3838
3839 /*
3840 * The product Sxx * Syy might underflow or overflow. If so, we can
3841 * recover by computing sqrt(Sxx) * sqrt(Syy) instead of sqrt(Sxx * Syy).
3842 * However, the double sqrt() calculation is a bit slower and less
3843 * accurate, so don't do it if we don't have to.
3844 */
3845 product = Sxx * Syy;
3846 if (product == 0 || isinf(product))
3847 sqrtproduct = sqrt(Sxx) * sqrt(Syy);
3848 else
3849 sqrtproduct = sqrt(product);
3850 result = Sxy / sqrtproduct;
3851
3852 /*
3853 * Despite all these precautions, this formula can yield results outside
3854 * [-1, 1] due to roundoff error. Clamp it to the expected range.
3855 */
3856 if (result < -1)
3857 result = -1;
3858 else if (result > 1)
3859 result = 1;
3860
3861 PG_RETURN_FLOAT8(result);
3862}
3863
3864Datum
3866{
3867 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3868 float8 *transvalues;
3869 float8 N,
3870 Sxx,
3871 Syy,
3872 Sxy;
3873
3874 transvalues = check_float8_array(transarray, "float8_regr_r2", 8);
3875 N = transvalues[0];
3876 Sxx = transvalues[2];
3877 Syy = transvalues[4];
3878 Sxy = transvalues[5];
3879
3880 /* if N is 0 we should return NULL */
3881 if (N < 1.0)
3883
3884 /* Note that Sxx and Syy are guaranteed to be non-negative */
3885
3886 /* per spec, return NULL for a vertical line */
3887 if (Sxx == 0)
3889
3890 /* per spec, return 1.0 for a horizontal line */
3891 if (Syy == 0)
3892 PG_RETURN_FLOAT8(1.0);
3893
3894 PG_RETURN_FLOAT8((Sxy * Sxy) / (Sxx * Syy));
3895}
3896
3897Datum
3899{
3900 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3901 float8 *transvalues;
3902 float8 N,
3903 Sxx,
3904 Sxy;
3905
3906 transvalues = check_float8_array(transarray, "float8_regr_slope", 8);
3907 N = transvalues[0];
3908 Sxx = transvalues[2];
3909 Sxy = transvalues[5];
3910
3911 /* if N is 0 we should return NULL */
3912 if (N < 1.0)
3914
3915 /* Note that Sxx is guaranteed to be non-negative */
3916
3917 /* per spec, return NULL for a vertical line */
3918 if (Sxx == 0)
3920
3921 PG_RETURN_FLOAT8(Sxy / Sxx);
3922}
3923
3924Datum
3926{
3927 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3928 float8 *transvalues;
3929 float8 N,
3930 Sx,
3931 Sxx,
3932 Sy,
3933 Sxy;
3934
3935 transvalues = check_float8_array(transarray, "float8_regr_intercept", 8);
3936 N = transvalues[0];
3937 Sx = transvalues[1];
3938 Sxx = transvalues[2];
3939 Sy = transvalues[3];
3940 Sxy = transvalues[5];
3941
3942 /* if N is 0 we should return NULL */
3943 if (N < 1.0)
3945
3946 /* Note that Sxx is guaranteed to be non-negative */
3947
3948 /* per spec, return NULL for a vertical line */
3949 if (Sxx == 0)
3951
3952 PG_RETURN_FLOAT8((Sy - Sx * Sxy / Sxx) / N);
3953}
3954
3955
3956/*
3957 * ====================================
3958 * MIXED-PRECISION ARITHMETIC OPERATORS
3959 * ====================================
3960 */
3961
3962/*
3963 * float48pl - returns arg1 + arg2
3964 * float48mi - returns arg1 - arg2
3965 * float48mul - returns arg1 * arg2
3966 * float48div - returns arg1 / arg2
3967 */
3968Datum
3970{
3971 float4 arg1 = PG_GETARG_FLOAT4(0);
3972 float8 arg2 = PG_GETARG_FLOAT8(1);
3973
3974 PG_RETURN_FLOAT8(float8_pl((float8) arg1, arg2));
3975}
3976
3977Datum
3979{
3980 float4 arg1 = PG_GETARG_FLOAT4(0);
3981 float8 arg2 = PG_GETARG_FLOAT8(1);
3982
3983 PG_RETURN_FLOAT8(float8_mi((float8) arg1, arg2));
3984}
3985
3986Datum
3988{
3989 float4 arg1 = PG_GETARG_FLOAT4(0);
3990 float8 arg2 = PG_GETARG_FLOAT8(1);
3991
3992 PG_RETURN_FLOAT8(float8_mul((float8) arg1, arg2));
3993}
3994
3995Datum
3997{
3998 float4 arg1 = PG_GETARG_FLOAT4(0);
3999 float8 arg2 = PG_GETARG_FLOAT8(1);
4000
4001 PG_RETURN_FLOAT8(float8_div((float8) arg1, arg2));
4002}
4003
4004/*
4005 * float84pl - returns arg1 + arg2
4006 * float84mi - returns arg1 - arg2
4007 * float84mul - returns arg1 * arg2
4008 * float84div - returns arg1 / arg2
4009 */
4010Datum
4012{
4013 float8 arg1 = PG_GETARG_FLOAT8(0);
4014 float4 arg2 = PG_GETARG_FLOAT4(1);
4015
4016 PG_RETURN_FLOAT8(float8_pl(arg1, (float8) arg2));
4017}
4018
4019Datum
4021{
4022 float8 arg1 = PG_GETARG_FLOAT8(0);
4023 float4 arg2 = PG_GETARG_FLOAT4(1);
4024
4025 PG_RETURN_FLOAT8(float8_mi(arg1, (float8) arg2));
4026}
4027
4028Datum
4030{
4031 float8 arg1 = PG_GETARG_FLOAT8(0);
4032 float4 arg2 = PG_GETARG_FLOAT4(1);
4033
4034 PG_RETURN_FLOAT8(float8_mul(arg1, (float8) arg2));
4035}
4036
4037Datum
4039{
4040 float8 arg1 = PG_GETARG_FLOAT8(0);
4041 float4 arg2 = PG_GETARG_FLOAT4(1);
4042
4043 PG_RETURN_FLOAT8(float8_div(arg1, (float8) arg2));
4044}
4045
4046/*
4047 * ====================
4048 * COMPARISON OPERATORS
4049 * ====================
4050 */
4051
4052/*
4053 * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
4054 */
4055Datum
4057{
4058 float4 arg1 = PG_GETARG_FLOAT4(0);
4059 float8 arg2 = PG_GETARG_FLOAT8(1);
4060
4061 PG_RETURN_BOOL(float8_eq((float8) arg1, arg2));
4062}
4063
4064Datum
4066{
4067 float4 arg1 = PG_GETARG_FLOAT4(0);
4068 float8 arg2 = PG_GETARG_FLOAT8(1);
4069
4070 PG_RETURN_BOOL(float8_ne((float8) arg1, arg2));
4071}
4072
4073Datum
4075{
4076 float4 arg1 = PG_GETARG_FLOAT4(0);
4077 float8 arg2 = PG_GETARG_FLOAT8(1);
4078
4079 PG_RETURN_BOOL(float8_lt((float8) arg1, arg2));
4080}
4081
4082Datum
4084{
4085 float4 arg1 = PG_GETARG_FLOAT4(0);
4086 float8 arg2 = PG_GETARG_FLOAT8(1);
4087
4088 PG_RETURN_BOOL(float8_le((float8) arg1, arg2));
4089}
4090
4091Datum
4093{
4094 float4 arg1 = PG_GETARG_FLOAT4(0);
4095 float8 arg2 = PG_GETARG_FLOAT8(1);
4096
4097 PG_RETURN_BOOL(float8_gt((float8) arg1, arg2));
4098}
4099
4100Datum
4102{
4103 float4 arg1 = PG_GETARG_FLOAT4(0);
4104 float8 arg2 = PG_GETARG_FLOAT8(1);
4105
4106 PG_RETURN_BOOL(float8_ge((float8) arg1, arg2));
4107}
4108
4109/*
4110 * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
4111 */
4112Datum
4114{
4115 float8 arg1 = PG_GETARG_FLOAT8(0);
4116 float4 arg2 = PG_GETARG_FLOAT4(1);
4117
4118 PG_RETURN_BOOL(float8_eq(arg1, (float8) arg2));
4119}
4120
4121Datum
4123{
4124 float8 arg1 = PG_GETARG_FLOAT8(0);
4125 float4 arg2 = PG_GETARG_FLOAT4(1);
4126
4127 PG_RETURN_BOOL(float8_ne(arg1, (float8) arg2));
4128}
4129
4130Datum
4132{
4133 float8 arg1 = PG_GETARG_FLOAT8(0);
4134 float4 arg2 = PG_GETARG_FLOAT4(1);
4135
4136 PG_RETURN_BOOL(float8_lt(arg1, (float8) arg2));
4137}
4138
4139Datum
4141{
4142 float8 arg1 = PG_GETARG_FLOAT8(0);
4143 float4 arg2 = PG_GETARG_FLOAT4(1);
4144
4145 PG_RETURN_BOOL(float8_le(arg1, (float8) arg2));
4146}
4147
4148Datum
4150{
4151 float8 arg1 = PG_GETARG_FLOAT8(0);
4152 float4 arg2 = PG_GETARG_FLOAT4(1);
4153
4154 PG_RETURN_BOOL(float8_gt(arg1, (float8) arg2));
4155}
4156
4157Datum
4159{
4160 float8 arg1 = PG_GETARG_FLOAT8(0);
4161 float4 arg2 = PG_GETARG_FLOAT4(1);
4162
4163 PG_RETURN_BOOL(float8_ge(arg1, (float8) arg2));
4164}
4165
4166/*
4167 * Implements the float8 version of the width_bucket() function
4168 * defined by SQL2003. See also width_bucket_numeric().
4169 *
4170 * 'bound1' and 'bound2' are the lower and upper bounds of the
4171 * histogram's range, respectively. 'count' is the number of buckets
4172 * in the histogram. width_bucket() returns an integer indicating the
4173 * bucket number that 'operand' belongs to in an equiwidth histogram
4174 * with the specified characteristics. An operand smaller than the
4175 * lower bound is assigned to bucket 0. An operand greater than or equal
4176 * to the upper bound is assigned to an additional bucket (with number
4177 * count+1). We don't allow the histogram bounds to be NaN or +/- infinity,
4178 * but we do allow those values for the operand (taking NaN to be larger
4179 * than any other value, as we do in comparisons).
4180 */
4181Datum
4183{
4184 float8 operand = PG_GETARG_FLOAT8(0);
4185 float8 bound1 = PG_GETARG_FLOAT8(1);
4186 float8 bound2 = PG_GETARG_FLOAT8(2);
4187 int32 count = PG_GETARG_INT32(3);
4188 int32 result;
4189
4190 if (count <= 0)
4191 ereport(ERROR,
4192 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4193 errmsg("count must be greater than zero")));
4194
4195 if (isnan(bound1) || isnan(bound2))
4196 ereport(ERROR,
4197 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4198 errmsg("lower and upper bounds cannot be NaN")));
4199
4200 if (isinf(bound1) || isinf(bound2))
4201 ereport(ERROR,
4202 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4203 errmsg("lower and upper bounds must be finite")));
4204
4205 if (bound1 < bound2)
4206 {
4207 if (isnan(operand) || operand >= bound2)
4208 {
4209 if (pg_add_s32_overflow(count, 1, &result))
4210 ereport(ERROR,
4211 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4212 errmsg("integer out of range")));
4213 }
4214 else if (operand < bound1)
4215 result = 0;
4216 else
4217 {
4218 if (!isinf(bound2 - bound1))
4219 {
4220 /* The quotient is surely in [0,1], so this can't overflow */
4221 result = count * ((operand - bound1) / (bound2 - bound1));
4222 }
4223 else
4224 {
4225 /*
4226 * We get here if bound2 - bound1 overflows DBL_MAX. Since
4227 * both bounds are finite, their difference can't exceed twice
4228 * DBL_MAX; so we can perform the computation without overflow
4229 * by dividing all the inputs by 2. That should be exact too,
4230 * except in the case where a very small operand underflows to
4231 * zero, which would have negligible impact on the result
4232 * given such large bounds.
4233 */
4234 result = count * ((operand / 2 - bound1 / 2) / (bound2 / 2 - bound1 / 2));
4235 }
4236 /* The quotient could round to 1.0, which would be a lie */
4237 if (result >= count)
4238 result = count - 1;
4239 /* Having done that, we can add 1 without fear of overflow */
4240 result++;
4241 }
4242 }
4243 else if (bound1 > bound2)
4244 {
4245 if (isnan(operand) || operand > bound1)
4246 result = 0;
4247 else if (operand <= bound2)
4248 {
4249 if (pg_add_s32_overflow(count, 1, &result))
4250 ereport(ERROR,
4251 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4252 errmsg("integer out of range")));
4253 }
4254 else
4255 {
4256 if (!isinf(bound1 - bound2))
4257 result = count * ((bound1 - operand) / (bound1 - bound2));
4258 else
4259 result = count * ((bound1 / 2 - operand / 2) / (bound1 / 2 - bound2 / 2));
4260 if (result >= count)
4261 result = count - 1;
4262 result++;
4263 }
4264 }
4265 else
4266 {
4267 ereport(ERROR,
4268 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
4269 errmsg("lower bound cannot equal upper bound")));
4270 result = 0; /* keep the compiler quiet */
4271 }
4272
4273 PG_RETURN_INT32(result);
4274}
#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:3382
#define FLOAT4_FITS_IN_INT32(num)
Definition: c.h:1096
#define FLOAT8_FITS_IN_INT32(num)
Definition: c.h:1102
#define pg_noinline
Definition: c.h:301
#define FLOAT4_FITS_IN_INT16(num)
Definition: c.h:1094
double float8
Definition: c.h:649
int16_t int16
Definition: c.h:547
int32_t int32
Definition: c.h:548
#define FLOAT8_FITS_IN_INT16(num)
Definition: c.h:1100
#define unlikely(x)
Definition: c.h:418
float float4
Definition: c.h:648
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:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#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:150
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:4149
Datum dasinh(PG_FUNCTION_ARGS)
Definition: float.c:2672
Datum float84mi(PG_FUNCTION_ARGS)
Definition: float.c:4020
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:4182
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:3681
Datum float48gt(PG_FUNCTION_ARGS)
Definition: float.c:4092
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:3865
Datum float8_regr_combine(PG_FUNCTION_ARGS)
Definition: float.c:3502
Datum float8_regr_slope(PG_FUNCTION_ARGS)
Definition: float.c:3898
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:4029
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:3969
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:3773
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:3925
Datum float8out(PG_FUNCTION_ARGS)
Definition: float.c:522
Datum float84le(PG_FUNCTION_ARGS)
Definition: float.c:4140
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:4113
Datum float84lt(PG_FUNCTION_ARGS)
Definition: float.c:4131
Datum float48mi(PG_FUNCTION_ARGS)
Definition: float.c:3978
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:4056
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:4011
Datum btfloat48cmp(PG_FUNCTION_ARGS)
Definition: float.c:1001
Datum float48ge(PG_FUNCTION_ARGS)
Definition: float.c:4101
Datum float84div(PG_FUNCTION_ARGS)
Definition: float.c:4038
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:4158
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:3702
Datum float8_var_pop(PG_FUNCTION_ARGS)
Definition: float.c:3227
Datum float48div(PG_FUNCTION_ARGS)
Definition: float.c:3996
Datum float84ne(PG_FUNCTION_ARGS)
Definition: float.c:4122
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:4083
Datum float8_regr_sxx(PG_FUNCTION_ARGS)
Definition: float.c:3660
Datum float8_corr(PG_FUNCTION_ARGS)
Definition: float.c:3811
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:4065
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:4074
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:3723
Datum float8um(PG_FUNCTION_ARGS)
Definition: float.c:669
Datum float8_regr_avgy(PG_FUNCTION_ARGS)
Definition: float.c:3748
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:3792
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:3987
Datum float4smaller(PG_FUNCTION_ARGS)
Definition: float.c:634
Datum float8_regr_accum(PG_FUNCTION_ARGS)
Definition: float.c:3348
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:163
static float4 float4_div(const float4 val1, const float4 val2)
Definition: float.h:177
#define RADIANS_PER_DEGREE
Definition: float.h:26
static float4 get_float4_infinity(void)
Definition: float.h:58
static bool float4_lt(const float4 val1, const float4 val2)
Definition: float.h:241
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:113
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:137
static bool float4_ge(const float4 val1, const float4 val2)
Definition: float.h:277
static float4 get_float4_nan(void)
Definition: float.h:77
static bool float8_ne(const float8 val1, const float8 val2)
Definition: float.h:235
static bool float4_ne(const float4 val1, const float4 val2)
Definition: float.h:229
static float4 float4_pl(const float4 val1, const float4 val2)
Definition: float.h:101
static bool float4_eq(const float4 val1, const float4 val2)
Definition: float.h:217
static float4 float4_mul(const float4 val1, const float4 val2)
Definition: float.h:149
static float8 get_float8_infinity(void)
Definition: float.h:65
static bool float8_ge(const float8 val1, const float8 val2)
Definition: float.h:283
static float4 float4_mi(const float4 val1, const float4 val2)
Definition: float.h:125
static bool float8_le(const float8 val1, const float8 val2)
Definition: float.h:259
static bool float4_gt(const float4 val1, const float4 val2)
Definition: float.h:265
static bool float8_eq(const float8 val1, const float8 val2)
Definition: float.h:223
static bool float4_le(const float4 val1, const float4 val2)
Definition: float.h:253
static float8 get_float8_nan(void)
Definition: float.h:84
static float8 float8_div(const float8 val1, const float8 val2)
Definition: float.h:193
static bool float8_lt(const float8 val1, const float8 val2)
Definition: float.h:247
static bool float8_gt(const float8 val1, const float8 val2)
Definition: float.h:271
#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:1759
void * palloc(Size size)
Definition: mcxt.c:1365
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4607
Datum ascii(PG_FUNCTION_ARGS)
void * arg
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:71
static int scale
Definition: pgbench.c:182
int pg_strfromd(char *str, size_t count, int precision, double value)
Definition: snprintf.c:1276
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:65
static float4 DatumGetFloat4(Datum X)
Definition: postgres.h:441
#define Float8GetDatumFast(X)
Definition: postgres.h:517
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:475
uint64_t Datum
Definition: postgres.h:70
float4 pq_getmsgfloat4(StringInfo msg)
Definition: pqformat.c:468
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:487
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:325
void pq_sendfloat4(StringInfo buf, float4 f)
Definition: pqformat.c:252
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:345
void pq_sendfloat8(StringInfo buf, float8 f)
Definition: pqformat.c:276
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
struct StringInfoData * StringInfo
Definition: string.h:15
Definition: nodes.h:135
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106