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