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