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-2017, 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 "libpq/pqformat.h"
25 #include "utils/array.h"
26 #include "utils/builtins.h"
27 #include "utils/sortsupport.h"
28 
29 
30 #ifndef M_PI
31 /* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
32 #define M_PI 3.14159265358979323846
33 #endif
34 
35 /* Radians per degree, a.k.a. PI / 180 */
36 #define RADIANS_PER_DEGREE 0.0174532925199432957692
37 
38 /* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. NAN definition from
39  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrfNotNumberNANItems.asp
40  */
41 #if defined(WIN32) && !defined(NAN)
42 static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
43 
44 #define NAN (*(const double *) nan)
45 #endif
46 
47 /* not sure what the following should be, but better to make it over-sufficient */
48 #define MAXFLOATWIDTH 64
49 #define MAXDOUBLEWIDTH 128
50 
51 /*
52  * check to see if a float4/8 val has underflowed or overflowed
53  */
54 #define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid) \
55 do { \
56  if (isinf(val) && !(inf_is_valid)) \
57  ereport(ERROR, \
58  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
59  errmsg("value out of range: overflow"))); \
60  \
61  if ((val) == 0.0 && !(zero_is_valid)) \
62  ereport(ERROR, \
63  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
64  errmsg("value out of range: underflow"))); \
65 } while(0)
66 
67 
68 /* Configurable GUC parameter */
69 int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
70 
71 /* Cached constants for degree-based trig functions */
72 static bool degree_consts_set = false;
73 static float8 sin_30 = 0;
75 static float8 asin_0_5 = 0;
76 static float8 acos_0_5 = 0;
77 static float8 atan_1_0 = 0;
78 static float8 tan_45 = 0;
79 static float8 cot_45 = 0;
80 
81 /*
82  * These are intentionally not static; don't "fix" them. They will never
83  * be referenced by other files, much less changed; but we don't want the
84  * compiler to know that, else it might try to precompute expressions
85  * involving them. See comments for init_degree_constants().
86  */
92 
93 /* Local function prototypes */
94 static double sind_q1(double x);
95 static double cosd_q1(double x);
96 static void init_degree_constants(void);
97 
98 #ifndef HAVE_CBRT
99 /*
100  * Some machines (in particular, some versions of AIX) have an extern
101  * declaration for cbrt() in <math.h> but fail to provide the actual
102  * function, which causes configure to not set HAVE_CBRT. Furthermore,
103  * their compilers spit up at the mismatch between extern declaration
104  * and static definition. We work around that here by the expedient
105  * of a #define to make the actual name of the static function different.
106  */
107 #define cbrt my_cbrt
108 static double cbrt(double x);
109 #endif /* HAVE_CBRT */
110 
111 
112 /*
113  * Routines to provide reasonably platform-independent handling of
114  * infinity and NaN. We assume that isinf() and isnan() are available
115  * and work per spec. (On some platforms, we have to supply our own;
116  * see src/port.) However, generating an Infinity or NaN in the first
117  * place is less well standardized; pre-C99 systems tend not to have C99's
118  * INFINITY and NAN macros. We centralize our workarounds for this here.
119  */
120 
121 double
123 {
124 #ifdef INFINITY
125  /* C99 standard way */
126  return (double) INFINITY;
127 #else
128 
129  /*
130  * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
131  * largest normal double. We assume forcing an overflow will get us a
132  * true infinity.
133  */
134  return (double) (HUGE_VAL * HUGE_VAL);
135 #endif
136 }
137 
138 /*
139 * The funny placements of the two #pragmas is necessary because of a
140 * long lived bug in the Microsoft compilers.
141 * See http://support.microsoft.com/kb/120968/en-us for details
142 */
143 #if (_MSC_VER >= 1800)
144 #pragma warning(disable:4756)
145 #endif
146 float
148 {
149 #ifdef INFINITY
150  /* C99 standard way */
151  return (float) INFINITY;
152 #else
153 #if (_MSC_VER >= 1800)
154 #pragma warning(default:4756)
155 #endif
156 
157  /*
158  * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
159  * largest normal double. We assume forcing an overflow will get us a
160  * true infinity.
161  */
162  return (float) (HUGE_VAL * HUGE_VAL);
163 #endif
164 }
165 
166 double
168 {
169  /* (double) NAN doesn't work on some NetBSD/MIPS releases */
170 #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
171  /* C99 standard way */
172  return (double) NAN;
173 #else
174  /* Assume we can get a NAN via zero divide */
175  return (double) (0.0 / 0.0);
176 #endif
177 }
178 
179 float
181 {
182 #ifdef NAN
183  /* C99 standard way */
184  return (float) NAN;
185 #else
186  /* Assume we can get a NAN via zero divide */
187  return (float) (0.0 / 0.0);
188 #endif
189 }
190 
191 
192 /*
193  * Returns -1 if 'val' represents negative infinity, 1 if 'val'
194  * represents (positive) infinity, and 0 otherwise. On some platforms,
195  * this is equivalent to the isinf() macro, but not everywhere: C99
196  * does not specify that isinf() needs to distinguish between positive
197  * and negative infinity.
198  */
199 int
201 {
202  int inf = isinf(val);
203 
204  if (inf == 0)
205  return 0;
206  else if (val > 0)
207  return 1;
208  else
209  return -1;
210 }
211 
212 
213 /* ========== USER I/O ROUTINES ========== */
214 
215 
216 /*
217  * float4in - converts "num" to float4
218  */
219 Datum
221 {
222  char *num = PG_GETARG_CSTRING(0);
223  char *orig_num;
224  double val;
225  char *endptr;
226 
227  /*
228  * endptr points to the first character _after_ the sequence we recognized
229  * as a valid floating point number. orig_num points to the original input
230  * string.
231  */
232  orig_num = num;
233 
234  /* skip leading whitespace */
235  while (*num != '\0' && isspace((unsigned char) *num))
236  num++;
237 
238  /*
239  * Check for an empty-string input to begin with, to avoid the vagaries of
240  * strtod() on different platforms.
241  */
242  if (*num == '\0')
243  ereport(ERROR,
244  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
245  errmsg("invalid input syntax for type %s: \"%s\"",
246  "real", orig_num)));
247 
248  errno = 0;
249  val = strtod(num, &endptr);
250 
251  /* did we not see anything that looks like a double? */
252  if (endptr == num || errno != 0)
253  {
254  int save_errno = errno;
255 
256  /*
257  * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
258  * but not all platforms support all of these (and some accept them
259  * but set ERANGE anyway...) Therefore, we check for these inputs
260  * ourselves if strtod() fails.
261  *
262  * Note: C99 also requires hexadecimal input as well as some extended
263  * forms of NaN, but we consider these forms unportable and don't try
264  * to support them. You can use 'em if your strtod() takes 'em.
265  */
266  if (pg_strncasecmp(num, "NaN", 3) == 0)
267  {
268  val = get_float4_nan();
269  endptr = num + 3;
270  }
271  else if (pg_strncasecmp(num, "Infinity", 8) == 0)
272  {
273  val = get_float4_infinity();
274  endptr = num + 8;
275  }
276  else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
277  {
278  val = get_float4_infinity();
279  endptr = num + 9;
280  }
281  else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
282  {
283  val = -get_float4_infinity();
284  endptr = num + 9;
285  }
286  else if (pg_strncasecmp(num, "inf", 3) == 0)
287  {
288  val = get_float4_infinity();
289  endptr = num + 3;
290  }
291  else if (pg_strncasecmp(num, "+inf", 4) == 0)
292  {
293  val = get_float4_infinity();
294  endptr = num + 4;
295  }
296  else if (pg_strncasecmp(num, "-inf", 4) == 0)
297  {
298  val = -get_float4_infinity();
299  endptr = num + 4;
300  }
301  else if (save_errno == ERANGE)
302  {
303  /*
304  * Some platforms return ERANGE for denormalized numbers (those
305  * that are not zero, but are too close to zero to have full
306  * precision). We'd prefer not to throw error for that, so try to
307  * detect whether it's a "real" out-of-range condition by checking
308  * to see if the result is zero or huge.
309  */
310  if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
311  ereport(ERROR,
312  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
313  errmsg("\"%s\" is out of range for type real",
314  orig_num)));
315  }
316  else
317  ereport(ERROR,
318  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
319  errmsg("invalid input syntax for type %s: \"%s\"",
320  "real", orig_num)));
321  }
322 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
323  else
324  {
325  /*
326  * Many versions of Solaris have a bug wherein strtod sets endptr to
327  * point one byte beyond the end of the string when given "inf" or
328  * "infinity".
329  */
330  if (endptr != num && endptr[-1] == '\0')
331  endptr--;
332  }
333 #endif /* HAVE_BUGGY_SOLARIS_STRTOD */
334 
335  /* skip trailing whitespace */
336  while (*endptr != '\0' && isspace((unsigned char) *endptr))
337  endptr++;
338 
339  /* if there is any junk left at the end of the string, bail out */
340  if (*endptr != '\0')
341  ereport(ERROR,
342  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
343  errmsg("invalid input syntax for type %s: \"%s\"",
344  "real", orig_num)));
345 
346  /*
347  * if we get here, we have a legal double, still need to check to see if
348  * it's a legal float4
349  */
350  CHECKFLOATVAL((float4) val, isinf(val), val == 0);
351 
352  PG_RETURN_FLOAT4((float4) val);
353 }
354 
355 /*
356  * float4out - converts a float4 number to a string
357  * using a standard output format
358  */
359 Datum
361 {
362  float4 num = PG_GETARG_FLOAT4(0);
363  char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
364 
365  if (isnan(num))
366  PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
367 
368  switch (is_infinite(num))
369  {
370  case 1:
371  strcpy(ascii, "Infinity");
372  break;
373  case -1:
374  strcpy(ascii, "-Infinity");
375  break;
376  default:
377  {
378  int ndig = FLT_DIG + extra_float_digits;
379 
380  if (ndig < 1)
381  ndig = 1;
382 
383  snprintf(ascii, MAXFLOATWIDTH + 1, "%.*g", ndig, num);
384  }
385  }
386 
387  PG_RETURN_CSTRING(ascii);
388 }
389 
390 /*
391  * float4recv - converts external binary format to float4
392  */
393 Datum
395 {
397 
399 }
400 
401 /*
402  * float4send - converts float4 to binary format
403  */
404 Datum
406 {
407  float4 num = PG_GETARG_FLOAT4(0);
409 
410  pq_begintypsend(&buf);
411  pq_sendfloat4(&buf, num);
413 }
414 
415 /*
416  * float8in - converts "num" to float8
417  */
418 Datum
420 {
421  char *num = PG_GETARG_CSTRING(0);
422 
423  PG_RETURN_FLOAT8(float8in_internal(num, NULL, "double precision", num));
424 }
425 
426 /*
427  * float8in_internal - guts of float8in()
428  *
429  * This is exposed for use by functions that want a reasonably
430  * platform-independent way of inputting doubles. The behavior is
431  * essentially like strtod + ereport on error, but note the following
432  * differences:
433  * 1. Both leading and trailing whitespace are skipped.
434  * 2. If endptr_p is NULL, we throw error if there's trailing junk.
435  * Otherwise, it's up to the caller to complain about trailing junk.
436  * 3. In event of a syntax error, the report mentions the given type_name
437  * and prints orig_string as the input; this is meant to support use of
438  * this function with types such as "box" and "point", where what we are
439  * parsing here is just a substring of orig_string.
440  *
441  * "num" could validly be declared "const char *", but that results in an
442  * unreasonable amount of extra casting both here and in callers, so we don't.
443  */
444 double
445 float8in_internal(char *num, char **endptr_p,
446  const char *type_name, const char *orig_string)
447 {
448  double val;
449  char *endptr;
450 
451  /* skip leading whitespace */
452  while (*num != '\0' && isspace((unsigned char) *num))
453  num++;
454 
455  /*
456  * Check for an empty-string input to begin with, to avoid the vagaries of
457  * strtod() on different platforms.
458  */
459  if (*num == '\0')
460  ereport(ERROR,
461  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
462  errmsg("invalid input syntax for type %s: \"%s\"",
463  type_name, orig_string)));
464 
465  errno = 0;
466  val = strtod(num, &endptr);
467 
468  /* did we not see anything that looks like a double? */
469  if (endptr == num || errno != 0)
470  {
471  int save_errno = errno;
472 
473  /*
474  * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
475  * but not all platforms support all of these (and some accept them
476  * but set ERANGE anyway...) Therefore, we check for these inputs
477  * ourselves if strtod() fails.
478  *
479  * Note: C99 also requires hexadecimal input as well as some extended
480  * forms of NaN, but we consider these forms unportable and don't try
481  * to support them. You can use 'em if your strtod() takes 'em.
482  */
483  if (pg_strncasecmp(num, "NaN", 3) == 0)
484  {
485  val = get_float8_nan();
486  endptr = num + 3;
487  }
488  else if (pg_strncasecmp(num, "Infinity", 8) == 0)
489  {
490  val = get_float8_infinity();
491  endptr = num + 8;
492  }
493  else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
494  {
495  val = get_float8_infinity();
496  endptr = num + 9;
497  }
498  else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
499  {
500  val = -get_float8_infinity();
501  endptr = num + 9;
502  }
503  else if (pg_strncasecmp(num, "inf", 3) == 0)
504  {
505  val = get_float8_infinity();
506  endptr = num + 3;
507  }
508  else if (pg_strncasecmp(num, "+inf", 4) == 0)
509  {
510  val = get_float8_infinity();
511  endptr = num + 4;
512  }
513  else if (pg_strncasecmp(num, "-inf", 4) == 0)
514  {
515  val = -get_float8_infinity();
516  endptr = num + 4;
517  }
518  else if (save_errno == ERANGE)
519  {
520  /*
521  * Some platforms return ERANGE for denormalized numbers (those
522  * that are not zero, but are too close to zero to have full
523  * precision). We'd prefer not to throw error for that, so try to
524  * detect whether it's a "real" out-of-range condition by checking
525  * to see if the result is zero or huge.
526  *
527  * On error, we intentionally complain about double precision not
528  * the given type name, and we print only the part of the string
529  * that is the current number.
530  */
531  if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
532  {
533  char *errnumber = pstrdup(num);
534 
535  errnumber[endptr - num] = '\0';
536  ereport(ERROR,
537  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
538  errmsg("\"%s\" is out of range for type double precision",
539  errnumber)));
540  }
541  }
542  else
543  ereport(ERROR,
544  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
545  errmsg("invalid input syntax for type %s: \"%s\"",
546  type_name, orig_string)));
547  }
548 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
549  else
550  {
551  /*
552  * Many versions of Solaris have a bug wherein strtod sets endptr to
553  * point one byte beyond the end of the string when given "inf" or
554  * "infinity".
555  */
556  if (endptr != num && endptr[-1] == '\0')
557  endptr--;
558  }
559 #endif /* HAVE_BUGGY_SOLARIS_STRTOD */
560 
561  /* skip trailing whitespace */
562  while (*endptr != '\0' && isspace((unsigned char) *endptr))
563  endptr++;
564 
565  /* report stopping point if wanted, else complain if not end of string */
566  if (endptr_p)
567  *endptr_p = endptr;
568  else if (*endptr != '\0')
569  ereport(ERROR,
570  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
571  errmsg("invalid input syntax for type %s: \"%s\"",
572  type_name, orig_string)));
573 
574  return val;
575 }
576 
577 /*
578  * float8out - converts float8 number to a string
579  * using a standard output format
580  */
581 Datum
583 {
584  float8 num = PG_GETARG_FLOAT8(0);
585 
587 }
588 
589 /*
590  * float8out_internal - guts of float8out()
591  *
592  * This is exposed for use by functions that want a reasonably
593  * platform-independent way of outputting doubles.
594  * The result is always palloc'd.
595  */
596 char *
598 {
599  char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
600 
601  if (isnan(num))
602  return strcpy(ascii, "NaN");
603 
604  switch (is_infinite(num))
605  {
606  case 1:
607  strcpy(ascii, "Infinity");
608  break;
609  case -1:
610  strcpy(ascii, "-Infinity");
611  break;
612  default:
613  {
614  int ndig = DBL_DIG + extra_float_digits;
615 
616  if (ndig < 1)
617  ndig = 1;
618 
619  snprintf(ascii, MAXDOUBLEWIDTH + 1, "%.*g", ndig, num);
620  }
621  }
622 
623  return ascii;
624 }
625 
626 /*
627  * float8recv - converts external binary format to float8
628  */
629 Datum
631 {
633 
635 }
636 
637 /*
638  * float8send - converts float8 to binary format
639  */
640 Datum
642 {
643  float8 num = PG_GETARG_FLOAT8(0);
645 
646  pq_begintypsend(&buf);
647  pq_sendfloat8(&buf, num);
649 }
650 
651 
652 /* ========== PUBLIC ROUTINES ========== */
653 
654 
655 /*
656  * ======================
657  * FLOAT4 BASE OPERATIONS
658  * ======================
659  */
660 
661 /*
662  * float4abs - returns |arg1| (absolute value)
663  */
664 Datum
666 {
667  float4 arg1 = PG_GETARG_FLOAT4(0);
668 
669  PG_RETURN_FLOAT4((float4) fabs(arg1));
670 }
671 
672 /*
673  * float4um - returns -arg1 (unary minus)
674  */
675 Datum
677 {
678  float4 arg1 = PG_GETARG_FLOAT4(0);
679  float4 result;
680 
681  result = -arg1;
682  PG_RETURN_FLOAT4(result);
683 }
684 
685 Datum
687 {
689 
690  PG_RETURN_FLOAT4(arg);
691 }
692 
693 Datum
695 {
696  float4 arg1 = PG_GETARG_FLOAT4(0);
697  float4 arg2 = PG_GETARG_FLOAT4(1);
698  float4 result;
699 
700  if (float4_cmp_internal(arg1, arg2) > 0)
701  result = arg1;
702  else
703  result = arg2;
704  PG_RETURN_FLOAT4(result);
705 }
706 
707 Datum
709 {
710  float4 arg1 = PG_GETARG_FLOAT4(0);
711  float4 arg2 = PG_GETARG_FLOAT4(1);
712  float4 result;
713 
714  if (float4_cmp_internal(arg1, arg2) < 0)
715  result = arg1;
716  else
717  result = arg2;
718  PG_RETURN_FLOAT4(result);
719 }
720 
721 /*
722  * ======================
723  * FLOAT8 BASE OPERATIONS
724  * ======================
725  */
726 
727 /*
728  * float8abs - returns |arg1| (absolute value)
729  */
730 Datum
732 {
733  float8 arg1 = PG_GETARG_FLOAT8(0);
734 
735  PG_RETURN_FLOAT8(fabs(arg1));
736 }
737 
738 
739 /*
740  * float8um - returns -arg1 (unary minus)
741  */
742 Datum
744 {
745  float8 arg1 = PG_GETARG_FLOAT8(0);
746  float8 result;
747 
748  result = -arg1;
749  PG_RETURN_FLOAT8(result);
750 }
751 
752 Datum
754 {
756 
757  PG_RETURN_FLOAT8(arg);
758 }
759 
760 Datum
762 {
763  float8 arg1 = PG_GETARG_FLOAT8(0);
764  float8 arg2 = PG_GETARG_FLOAT8(1);
765  float8 result;
766 
767  if (float8_cmp_internal(arg1, arg2) > 0)
768  result = arg1;
769  else
770  result = arg2;
771  PG_RETURN_FLOAT8(result);
772 }
773 
774 Datum
776 {
777  float8 arg1 = PG_GETARG_FLOAT8(0);
778  float8 arg2 = PG_GETARG_FLOAT8(1);
779  float8 result;
780 
781  if (float8_cmp_internal(arg1, arg2) < 0)
782  result = arg1;
783  else
784  result = arg2;
785  PG_RETURN_FLOAT8(result);
786 }
787 
788 
789 /*
790  * ====================
791  * ARITHMETIC OPERATORS
792  * ====================
793  */
794 
795 /*
796  * float4pl - returns arg1 + arg2
797  * float4mi - returns arg1 - arg2
798  * float4mul - returns arg1 * arg2
799  * float4div - returns arg1 / arg2
800  */
801 Datum
803 {
804  float4 arg1 = PG_GETARG_FLOAT4(0);
805  float4 arg2 = PG_GETARG_FLOAT4(1);
806  float4 result;
807 
808  result = arg1 + arg2;
809 
810  /*
811  * There isn't any way to check for underflow of addition/subtraction
812  * because numbers near the underflow value have already been rounded to
813  * the point where we can't detect that the two values were originally
814  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
815  * 1.4013e-45.
816  */
817  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
818  PG_RETURN_FLOAT4(result);
819 }
820 
821 Datum
823 {
824  float4 arg1 = PG_GETARG_FLOAT4(0);
825  float4 arg2 = PG_GETARG_FLOAT4(1);
826  float4 result;
827 
828  result = arg1 - arg2;
829  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
830  PG_RETURN_FLOAT4(result);
831 }
832 
833 Datum
835 {
836  float4 arg1 = PG_GETARG_FLOAT4(0);
837  float4 arg2 = PG_GETARG_FLOAT4(1);
838  float4 result;
839 
840  result = arg1 * arg2;
841  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
842  arg1 == 0 || arg2 == 0);
843  PG_RETURN_FLOAT4(result);
844 }
845 
846 Datum
848 {
849  float4 arg1 = PG_GETARG_FLOAT4(0);
850  float4 arg2 = PG_GETARG_FLOAT4(1);
851  float4 result;
852 
853  if (arg2 == 0.0)
854  ereport(ERROR,
855  (errcode(ERRCODE_DIVISION_BY_ZERO),
856  errmsg("division by zero")));
857 
858  result = arg1 / arg2;
859 
860  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
861  PG_RETURN_FLOAT4(result);
862 }
863 
864 /*
865  * float8pl - returns arg1 + arg2
866  * float8mi - returns arg1 - arg2
867  * float8mul - returns arg1 * arg2
868  * float8div - returns arg1 / arg2
869  */
870 Datum
872 {
873  float8 arg1 = PG_GETARG_FLOAT8(0);
874  float8 arg2 = PG_GETARG_FLOAT8(1);
875  float8 result;
876 
877  result = arg1 + arg2;
878 
879  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
880  PG_RETURN_FLOAT8(result);
881 }
882 
883 Datum
885 {
886  float8 arg1 = PG_GETARG_FLOAT8(0);
887  float8 arg2 = PG_GETARG_FLOAT8(1);
888  float8 result;
889 
890  result = arg1 - arg2;
891 
892  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
893  PG_RETURN_FLOAT8(result);
894 }
895 
896 Datum
898 {
899  float8 arg1 = PG_GETARG_FLOAT8(0);
900  float8 arg2 = PG_GETARG_FLOAT8(1);
901  float8 result;
902 
903  result = arg1 * arg2;
904 
905  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
906  arg1 == 0 || arg2 == 0);
907  PG_RETURN_FLOAT8(result);
908 }
909 
910 Datum
912 {
913  float8 arg1 = PG_GETARG_FLOAT8(0);
914  float8 arg2 = PG_GETARG_FLOAT8(1);
915  float8 result;
916 
917  if (arg2 == 0.0)
918  ereport(ERROR,
919  (errcode(ERRCODE_DIVISION_BY_ZERO),
920  errmsg("division by zero")));
921 
922  result = arg1 / arg2;
923 
924  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
925  PG_RETURN_FLOAT8(result);
926 }
927 
928 
929 /*
930  * ====================
931  * COMPARISON OPERATORS
932  * ====================
933  */
934 
935 /*
936  * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
937  */
938 int
940 {
941  /*
942  * We consider all NANs to be equal and larger than any non-NAN. This is
943  * somewhat arbitrary; the important thing is to have a consistent sort
944  * order.
945  */
946  if (isnan(a))
947  {
948  if (isnan(b))
949  return 0; /* NAN = NAN */
950  else
951  return 1; /* NAN > non-NAN */
952  }
953  else if (isnan(b))
954  {
955  return -1; /* non-NAN < NAN */
956  }
957  else
958  {
959  if (a > b)
960  return 1;
961  else if (a < b)
962  return -1;
963  else
964  return 0;
965  }
966 }
967 
968 Datum
970 {
971  float4 arg1 = PG_GETARG_FLOAT4(0);
972  float4 arg2 = PG_GETARG_FLOAT4(1);
973 
974  PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);
975 }
976 
977 Datum
979 {
980  float4 arg1 = PG_GETARG_FLOAT4(0);
981  float4 arg2 = PG_GETARG_FLOAT4(1);
982 
983  PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);
984 }
985 
986 Datum
988 {
989  float4 arg1 = PG_GETARG_FLOAT4(0);
990  float4 arg2 = PG_GETARG_FLOAT4(1);
991 
992  PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);
993 }
994 
995 Datum
997 {
998  float4 arg1 = PG_GETARG_FLOAT4(0);
999  float4 arg2 = PG_GETARG_FLOAT4(1);
1000 
1001  PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);
1002 }
1003 
1004 Datum
1006 {
1007  float4 arg1 = PG_GETARG_FLOAT4(0);
1008  float4 arg2 = PG_GETARG_FLOAT4(1);
1009 
1010  PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);
1011 }
1012 
1013 Datum
1015 {
1016  float4 arg1 = PG_GETARG_FLOAT4(0);
1017  float4 arg2 = PG_GETARG_FLOAT4(1);
1018 
1019  PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);
1020 }
1021 
1022 Datum
1024 {
1025  float4 arg1 = PG_GETARG_FLOAT4(0);
1026  float4 arg2 = PG_GETARG_FLOAT4(1);
1027 
1028  PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
1029 }
1030 
1031 static int
1033 {
1034  float4 arg1 = DatumGetFloat4(x);
1035  float4 arg2 = DatumGetFloat4(y);
1036 
1037  return float4_cmp_internal(arg1, arg2);
1038 }
1039 
1040 Datum
1042 {
1044 
1045  ssup->comparator = btfloat4fastcmp;
1046  PG_RETURN_VOID();
1047 }
1048 
1049 /*
1050  * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
1051  */
1052 int
1054 {
1055  /*
1056  * We consider all NANs to be equal and larger than any non-NAN. This is
1057  * somewhat arbitrary; the important thing is to have a consistent sort
1058  * order.
1059  */
1060  if (isnan(a))
1061  {
1062  if (isnan(b))
1063  return 0; /* NAN = NAN */
1064  else
1065  return 1; /* NAN > non-NAN */
1066  }
1067  else if (isnan(b))
1068  {
1069  return -1; /* non-NAN < NAN */
1070  }
1071  else
1072  {
1073  if (a > b)
1074  return 1;
1075  else if (a < b)
1076  return -1;
1077  else
1078  return 0;
1079  }
1080 }
1081 
1082 Datum
1084 {
1085  float8 arg1 = PG_GETARG_FLOAT8(0);
1086  float8 arg2 = PG_GETARG_FLOAT8(1);
1087 
1088  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
1089 }
1090 
1091 Datum
1093 {
1094  float8 arg1 = PG_GETARG_FLOAT8(0);
1095  float8 arg2 = PG_GETARG_FLOAT8(1);
1096 
1097  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
1098 }
1099 
1100 Datum
1102 {
1103  float8 arg1 = PG_GETARG_FLOAT8(0);
1104  float8 arg2 = PG_GETARG_FLOAT8(1);
1105 
1106  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
1107 }
1108 
1109 Datum
1111 {
1112  float8 arg1 = PG_GETARG_FLOAT8(0);
1113  float8 arg2 = PG_GETARG_FLOAT8(1);
1114 
1115  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
1116 }
1117 
1118 Datum
1120 {
1121  float8 arg1 = PG_GETARG_FLOAT8(0);
1122  float8 arg2 = PG_GETARG_FLOAT8(1);
1123 
1124  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
1125 }
1126 
1127 Datum
1129 {
1130  float8 arg1 = PG_GETARG_FLOAT8(0);
1131  float8 arg2 = PG_GETARG_FLOAT8(1);
1132 
1133  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
1134 }
1135 
1136 Datum
1138 {
1139  float8 arg1 = PG_GETARG_FLOAT8(0);
1140  float8 arg2 = PG_GETARG_FLOAT8(1);
1141 
1142  PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1143 }
1144 
1145 static int
1147 {
1148  float8 arg1 = DatumGetFloat8(x);
1149  float8 arg2 = DatumGetFloat8(y);
1150 
1151  return float8_cmp_internal(arg1, arg2);
1152 }
1153 
1154 Datum
1156 {
1158 
1159  ssup->comparator = btfloat8fastcmp;
1160  PG_RETURN_VOID();
1161 }
1162 
1163 Datum
1165 {
1166  float4 arg1 = PG_GETARG_FLOAT4(0);
1167  float8 arg2 = PG_GETARG_FLOAT8(1);
1168 
1169  /* widen float4 to float8 and then compare */
1170  PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1171 }
1172 
1173 Datum
1175 {
1176  float8 arg1 = PG_GETARG_FLOAT8(0);
1177  float4 arg2 = PG_GETARG_FLOAT4(1);
1178 
1179  /* widen float4 to float8 and then compare */
1180  PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1181 }
1182 
1183 
1184 /*
1185  * ===================
1186  * CONVERSION ROUTINES
1187  * ===================
1188  */
1189 
1190 /*
1191  * ftod - converts a float4 number to a float8 number
1192  */
1193 Datum
1195 {
1196  float4 num = PG_GETARG_FLOAT4(0);
1197 
1198  PG_RETURN_FLOAT8((float8) num);
1199 }
1200 
1201 
1202 /*
1203  * dtof - converts a float8 number to a float4 number
1204  */
1205 Datum
1207 {
1208  float8 num = PG_GETARG_FLOAT8(0);
1209 
1210  CHECKFLOATVAL((float4) num, isinf(num), num == 0);
1211 
1212  PG_RETURN_FLOAT4((float4) num);
1213 }
1214 
1215 
1216 /*
1217  * dtoi4 - converts a float8 number to an int4 number
1218  */
1219 Datum
1221 {
1222  float8 num = PG_GETARG_FLOAT8(0);
1223  int32 result;
1224 
1225  /* 'Inf' is handled by INT_MAX */
1226  if (num < INT_MIN || num > INT_MAX || isnan(num))
1227  ereport(ERROR,
1228  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1229  errmsg("integer out of range")));
1230 
1231  result = (int32) rint(num);
1232  PG_RETURN_INT32(result);
1233 }
1234 
1235 
1236 /*
1237  * dtoi2 - converts a float8 number to an int2 number
1238  */
1239 Datum
1241 {
1242  float8 num = PG_GETARG_FLOAT8(0);
1243 
1244  if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
1245  ereport(ERROR,
1246  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1247  errmsg("smallint out of range")));
1248 
1249  PG_RETURN_INT16((int16) rint(num));
1250 }
1251 
1252 
1253 /*
1254  * i4tod - converts an int4 number to a float8 number
1255  */
1256 Datum
1258 {
1259  int32 num = PG_GETARG_INT32(0);
1260 
1261  PG_RETURN_FLOAT8((float8) num);
1262 }
1263 
1264 
1265 /*
1266  * i2tod - converts an int2 number to a float8 number
1267  */
1268 Datum
1270 {
1271  int16 num = PG_GETARG_INT16(0);
1272 
1273  PG_RETURN_FLOAT8((float8) num);
1274 }
1275 
1276 
1277 /*
1278  * ftoi4 - converts a float4 number to an int4 number
1279  */
1280 Datum
1282 {
1283  float4 num = PG_GETARG_FLOAT4(0);
1284 
1285  if (num < INT_MIN || num > INT_MAX || isnan(num))
1286  ereport(ERROR,
1287  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1288  errmsg("integer out of range")));
1289 
1290  PG_RETURN_INT32((int32) rint(num));
1291 }
1292 
1293 
1294 /*
1295  * ftoi2 - converts a float4 number to an int2 number
1296  */
1297 Datum
1299 {
1300  float4 num = PG_GETARG_FLOAT4(0);
1301 
1302  if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
1303  ereport(ERROR,
1304  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1305  errmsg("smallint out of range")));
1306 
1307  PG_RETURN_INT16((int16) rint(num));
1308 }
1309 
1310 
1311 /*
1312  * i4tof - converts an int4 number to a float4 number
1313  */
1314 Datum
1316 {
1317  int32 num = PG_GETARG_INT32(0);
1318 
1319  PG_RETURN_FLOAT4((float4) num);
1320 }
1321 
1322 
1323 /*
1324  * i2tof - converts an int2 number to a float4 number
1325  */
1326 Datum
1328 {
1329  int16 num = PG_GETARG_INT16(0);
1330 
1331  PG_RETURN_FLOAT4((float4) num);
1332 }
1333 
1334 
1335 /*
1336  * =======================
1337  * RANDOM FLOAT8 OPERATORS
1338  * =======================
1339  */
1340 
1341 /*
1342  * dround - returns ROUND(arg1)
1343  */
1344 Datum
1346 {
1347  float8 arg1 = PG_GETARG_FLOAT8(0);
1348 
1349  PG_RETURN_FLOAT8(rint(arg1));
1350 }
1351 
1352 /*
1353  * dceil - returns the smallest integer greater than or
1354  * equal to the specified float
1355  */
1356 Datum
1358 {
1359  float8 arg1 = PG_GETARG_FLOAT8(0);
1360 
1361  PG_RETURN_FLOAT8(ceil(arg1));
1362 }
1363 
1364 /*
1365  * dfloor - returns the largest integer lesser than or
1366  * equal to the specified float
1367  */
1368 Datum
1370 {
1371  float8 arg1 = PG_GETARG_FLOAT8(0);
1372 
1373  PG_RETURN_FLOAT8(floor(arg1));
1374 }
1375 
1376 /*
1377  * dsign - returns -1 if the argument is less than 0, 0
1378  * if the argument is equal to 0, and 1 if the
1379  * argument is greater than zero.
1380  */
1381 Datum
1383 {
1384  float8 arg1 = PG_GETARG_FLOAT8(0);
1385  float8 result;
1386 
1387  if (arg1 > 0)
1388  result = 1.0;
1389  else if (arg1 < 0)
1390  result = -1.0;
1391  else
1392  result = 0.0;
1393 
1394  PG_RETURN_FLOAT8(result);
1395 }
1396 
1397 /*
1398  * dtrunc - returns truncation-towards-zero of arg1,
1399  * arg1 >= 0 ... the greatest integer less
1400  * than or equal to arg1
1401  * arg1 < 0 ... the least integer greater
1402  * than or equal to arg1
1403  */
1404 Datum
1406 {
1407  float8 arg1 = PG_GETARG_FLOAT8(0);
1408  float8 result;
1409 
1410  if (arg1 >= 0)
1411  result = floor(arg1);
1412  else
1413  result = -floor(-arg1);
1414 
1415  PG_RETURN_FLOAT8(result);
1416 }
1417 
1418 
1419 /*
1420  * dsqrt - returns square root of arg1
1421  */
1422 Datum
1424 {
1425  float8 arg1 = PG_GETARG_FLOAT8(0);
1426  float8 result;
1427 
1428  if (arg1 < 0)
1429  ereport(ERROR,
1430  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1431  errmsg("cannot take square root of a negative number")));
1432 
1433  result = sqrt(arg1);
1434 
1435  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1436  PG_RETURN_FLOAT8(result);
1437 }
1438 
1439 
1440 /*
1441  * dcbrt - returns cube root of arg1
1442  */
1443 Datum
1445 {
1446  float8 arg1 = PG_GETARG_FLOAT8(0);
1447  float8 result;
1448 
1449  result = cbrt(arg1);
1450  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1451  PG_RETURN_FLOAT8(result);
1452 }
1453 
1454 
1455 /*
1456  * dpow - returns pow(arg1,arg2)
1457  */
1458 Datum
1460 {
1461  float8 arg1 = PG_GETARG_FLOAT8(0);
1462  float8 arg2 = PG_GETARG_FLOAT8(1);
1463  float8 result;
1464 
1465  /*
1466  * The SQL spec requires that we emit a particular SQLSTATE error code for
1467  * certain error conditions. Specifically, we don't return a
1468  * divide-by-zero error code for 0 ^ -1.
1469  */
1470  if (arg1 == 0 && arg2 < 0)
1471  ereport(ERROR,
1472  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1473  errmsg("zero raised to a negative power is undefined")));
1474  if (arg1 < 0 && floor(arg2) != arg2)
1475  ereport(ERROR,
1476  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1477  errmsg("a negative number raised to a non-integer power yields a complex result")));
1478 
1479  /*
1480  * pow() sets errno only on some platforms, depending on whether it
1481  * follows _IEEE_, _POSIX_, _XOPEN_, or _SVID_, so we try to avoid using
1482  * errno. However, some platform/CPU combinations return errno == EDOM
1483  * and result == Nan for negative arg1 and very large arg2 (they must be
1484  * using something different from our floor() test to decide it's
1485  * invalid). Other platforms (HPPA) return errno == ERANGE and a large
1486  * (HUGE_VAL) but finite result to signal overflow.
1487  */
1488  errno = 0;
1489  result = pow(arg1, arg2);
1490  if (errno == EDOM && isnan(result))
1491  {
1492  if ((fabs(arg1) > 1 && arg2 >= 0) || (fabs(arg1) < 1 && arg2 < 0))
1493  /* The sign of Inf is not significant in this case. */
1494  result = get_float8_infinity();
1495  else if (fabs(arg1) != 1)
1496  result = 0;
1497  else
1498  result = 1;
1499  }
1500  else if (errno == ERANGE && result != 0 && !isinf(result))
1501  result = get_float8_infinity();
1502 
1503  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
1504  PG_RETURN_FLOAT8(result);
1505 }
1506 
1507 
1508 /*
1509  * dexp - returns the exponential function of arg1
1510  */
1511 Datum
1513 {
1514  float8 arg1 = PG_GETARG_FLOAT8(0);
1515  float8 result;
1516 
1517  errno = 0;
1518  result = exp(arg1);
1519  if (errno == ERANGE && result != 0 && !isinf(result))
1520  result = get_float8_infinity();
1521 
1522  CHECKFLOATVAL(result, isinf(arg1), false);
1523  PG_RETURN_FLOAT8(result);
1524 }
1525 
1526 
1527 /*
1528  * dlog1 - returns the natural logarithm of arg1
1529  */
1530 Datum
1532 {
1533  float8 arg1 = PG_GETARG_FLOAT8(0);
1534  float8 result;
1535 
1536  /*
1537  * Emit particular SQLSTATE error codes for ln(). This is required by the
1538  * SQL standard.
1539  */
1540  if (arg1 == 0.0)
1541  ereport(ERROR,
1542  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1543  errmsg("cannot take logarithm of zero")));
1544  if (arg1 < 0)
1545  ereport(ERROR,
1546  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1547  errmsg("cannot take logarithm of a negative number")));
1548 
1549  result = log(arg1);
1550 
1551  CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
1552  PG_RETURN_FLOAT8(result);
1553 }
1554 
1555 
1556 /*
1557  * dlog10 - returns the base 10 logarithm of arg1
1558  */
1559 Datum
1561 {
1562  float8 arg1 = PG_GETARG_FLOAT8(0);
1563  float8 result;
1564 
1565  /*
1566  * Emit particular SQLSTATE error codes for log(). The SQL spec doesn't
1567  * define log(), but it does define ln(), so it makes sense to emit the
1568  * same error code for an analogous error condition.
1569  */
1570  if (arg1 == 0.0)
1571  ereport(ERROR,
1572  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1573  errmsg("cannot take logarithm of zero")));
1574  if (arg1 < 0)
1575  ereport(ERROR,
1576  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1577  errmsg("cannot take logarithm of a negative number")));
1578 
1579  result = log10(arg1);
1580 
1581  CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
1582  PG_RETURN_FLOAT8(result);
1583 }
1584 
1585 
1586 /*
1587  * dacos - returns the arccos of arg1 (radians)
1588  */
1589 Datum
1591 {
1592  float8 arg1 = PG_GETARG_FLOAT8(0);
1593  float8 result;
1594 
1595  /* Per the POSIX spec, return NaN if the input is NaN */
1596  if (isnan(arg1))
1598 
1599  /*
1600  * The principal branch of the inverse cosine function maps values in the
1601  * range [-1, 1] to values in the range [0, Pi], so we should reject any
1602  * inputs outside that range and the result will always be finite.
1603  */
1604  if (arg1 < -1.0 || arg1 > 1.0)
1605  ereport(ERROR,
1606  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1607  errmsg("input is out of range")));
1608 
1609  result = acos(arg1);
1610 
1611  CHECKFLOATVAL(result, false, true);
1612  PG_RETURN_FLOAT8(result);
1613 }
1614 
1615 
1616 /*
1617  * dasin - returns the arcsin of arg1 (radians)
1618  */
1619 Datum
1621 {
1622  float8 arg1 = PG_GETARG_FLOAT8(0);
1623  float8 result;
1624 
1625  /* Per the POSIX spec, return NaN if the input is NaN */
1626  if (isnan(arg1))
1628 
1629  /*
1630  * The principal branch of the inverse sine function maps values in the
1631  * range [-1, 1] to values in the range [-Pi/2, Pi/2], so we should reject
1632  * any inputs outside that range and the result will always be finite.
1633  */
1634  if (arg1 < -1.0 || arg1 > 1.0)
1635  ereport(ERROR,
1636  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1637  errmsg("input is out of range")));
1638 
1639  result = asin(arg1);
1640 
1641  CHECKFLOATVAL(result, false, true);
1642  PG_RETURN_FLOAT8(result);
1643 }
1644 
1645 
1646 /*
1647  * datan - returns the arctan of arg1 (radians)
1648  */
1649 Datum
1651 {
1652  float8 arg1 = PG_GETARG_FLOAT8(0);
1653  float8 result;
1654 
1655  /* Per the POSIX spec, return NaN if the input is NaN */
1656  if (isnan(arg1))
1658 
1659  /*
1660  * The principal branch of the inverse tangent function maps all inputs to
1661  * values in the range [-Pi/2, Pi/2], so the result should always be
1662  * finite, even if the input is infinite.
1663  */
1664  result = atan(arg1);
1665 
1666  CHECKFLOATVAL(result, false, true);
1667  PG_RETURN_FLOAT8(result);
1668 }
1669 
1670 
1671 /*
1672  * atan2 - returns the arctan of arg1/arg2 (radians)
1673  */
1674 Datum
1676 {
1677  float8 arg1 = PG_GETARG_FLOAT8(0);
1678  float8 arg2 = PG_GETARG_FLOAT8(1);
1679  float8 result;
1680 
1681  /* Per the POSIX spec, return NaN if either input is NaN */
1682  if (isnan(arg1) || isnan(arg2))
1684 
1685  /*
1686  * atan2 maps all inputs to values in the range [-Pi, Pi], so the result
1687  * should always be finite, even if the inputs are infinite.
1688  */
1689  result = atan2(arg1, arg2);
1690 
1691  CHECKFLOATVAL(result, false, true);
1692  PG_RETURN_FLOAT8(result);
1693 }
1694 
1695 
1696 /*
1697  * dcos - returns the cosine of arg1 (radians)
1698  */
1699 Datum
1701 {
1702  float8 arg1 = PG_GETARG_FLOAT8(0);
1703  float8 result;
1704 
1705  /* Per the POSIX spec, return NaN if the input is NaN */
1706  if (isnan(arg1))
1708 
1709  /*
1710  * cos() is periodic and so theoretically can work for all finite inputs,
1711  * but some implementations may choose to throw error if the input is so
1712  * large that there are no significant digits in the result. So we should
1713  * check for errors. POSIX allows an error to be reported either via
1714  * errno or via fetestexcept(), but currently we only support checking
1715  * errno. (fetestexcept() is rumored to report underflow unreasonably
1716  * early on some platforms, so it's not clear that believing it would be a
1717  * net improvement anyway.)
1718  *
1719  * For infinite inputs, POSIX specifies that the trigonometric functions
1720  * should return a domain error; but we won't notice that unless the
1721  * platform reports via errno, so also explicitly test for infinite
1722  * inputs.
1723  */
1724  errno = 0;
1725  result = cos(arg1);
1726  if (errno != 0 || isinf(arg1))
1727  ereport(ERROR,
1728  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1729  errmsg("input is out of range")));
1730 
1731  CHECKFLOATVAL(result, false, true);
1732  PG_RETURN_FLOAT8(result);
1733 }
1734 
1735 
1736 /*
1737  * dcot - returns the cotangent of arg1 (radians)
1738  */
1739 Datum
1741 {
1742  float8 arg1 = PG_GETARG_FLOAT8(0);
1743  float8 result;
1744 
1745  /* Per the POSIX spec, return NaN if the input is NaN */
1746  if (isnan(arg1))
1748 
1749  /* Be sure to throw an error if the input is infinite --- see dcos() */
1750  errno = 0;
1751  result = tan(arg1);
1752  if (errno != 0 || isinf(arg1))
1753  ereport(ERROR,
1754  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1755  errmsg("input is out of range")));
1756 
1757  result = 1.0 / result;
1758  CHECKFLOATVAL(result, true /* cot(0) == Inf */ , true);
1759  PG_RETURN_FLOAT8(result);
1760 }
1761 
1762 
1763 /*
1764  * dsin - returns the sine of arg1 (radians)
1765  */
1766 Datum
1768 {
1769  float8 arg1 = PG_GETARG_FLOAT8(0);
1770  float8 result;
1771 
1772  /* Per the POSIX spec, return NaN if the input is NaN */
1773  if (isnan(arg1))
1775 
1776  /* Be sure to throw an error if the input is infinite --- see dcos() */
1777  errno = 0;
1778  result = sin(arg1);
1779  if (errno != 0 || isinf(arg1))
1780  ereport(ERROR,
1781  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1782  errmsg("input is out of range")));
1783 
1784  CHECKFLOATVAL(result, false, true);
1785  PG_RETURN_FLOAT8(result);
1786 }
1787 
1788 
1789 /*
1790  * dtan - returns the tangent of arg1 (radians)
1791  */
1792 Datum
1794 {
1795  float8 arg1 = PG_GETARG_FLOAT8(0);
1796  float8 result;
1797 
1798  /* Per the POSIX spec, return NaN if the input is NaN */
1799  if (isnan(arg1))
1801 
1802  /* Be sure to throw an error if the input is infinite --- see dcos() */
1803  errno = 0;
1804  result = tan(arg1);
1805  if (errno != 0 || isinf(arg1))
1806  ereport(ERROR,
1807  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1808  errmsg("input is out of range")));
1809 
1810  CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */ , true);
1811  PG_RETURN_FLOAT8(result);
1812 }
1813 
1814 
1815 /* ========== DEGREE-BASED TRIGONOMETRIC FUNCTIONS ========== */
1816 
1817 
1818 /*
1819  * Initialize the cached constants declared at the head of this file
1820  * (sin_30 etc). The fact that we need those at all, let alone need this
1821  * Rube-Goldberg-worthy method of initializing them, is because there are
1822  * compilers out there that will precompute expressions such as sin(constant)
1823  * using a sin() function different from what will be used at runtime. If we
1824  * want exact results, we must ensure that none of the scaling constants used
1825  * in the degree-based trig functions are computed that way. To do so, we
1826  * compute them from the variables degree_c_thirty etc, which are also really
1827  * constants, but the compiler cannot assume that.
1828  *
1829  * Other hazards we are trying to forestall with this kluge include the
1830  * possibility that compilers will rearrange the expressions, or compute
1831  * some intermediate results in registers wider than a standard double.
1832  *
1833  * In the places where we use these constants, the typical pattern is like
1834  * volatile float8 sin_x = sin(x * RADIANS_PER_DEGREE);
1835  * return (sin_x / sin_30);
1836  * where we hope to get a value of exactly 1.0 from the division when x = 30.
1837  * The volatile temporary variable is needed on machines with wide float
1838  * registers, to ensure that the result of sin(x) is rounded to double width
1839  * the same as the value of sin_30 has been. Experimentation with gcc shows
1840  * that marking the temp variable volatile is necessary to make the store and
1841  * reload actually happen; hopefully the same trick works for other compilers.
1842  * (gcc's documentation suggests using the -ffloat-store compiler switch to
1843  * ensure this, but that is compiler-specific and it also pessimizes code in
1844  * many places where we don't care about this.)
1845  */
1846 static void
1848 {
1850  one_minus_cos_60 = 1.0 - cos(degree_c_sixty * RADIANS_PER_DEGREE);
1851  asin_0_5 = asin(degree_c_one_half);
1852  acos_0_5 = acos(degree_c_one_half);
1853  atan_1_0 = atan(degree_c_one);
1856  degree_consts_set = true;
1857 }
1858 
1859 #define INIT_DEGREE_CONSTANTS() \
1860 do { \
1861  if (!degree_consts_set) \
1862  init_degree_constants(); \
1863 } while(0)
1864 
1865 
1866 /*
1867  * asind_q1 - returns the inverse sine of x in degrees, for x in
1868  * the range [0, 1]. The result is an angle in the
1869  * first quadrant --- [0, 90] degrees.
1870  *
1871  * For the 3 special case inputs (0, 0.5 and 1), this
1872  * function will return exact values (0, 30 and 90
1873  * degrees respectively).
1874  */
1875 static double
1876 asind_q1(double x)
1877 {
1878  /*
1879  * Stitch together inverse sine and cosine functions for the ranges [0,
1880  * 0.5] and (0.5, 1]. Each expression below is guaranteed to return
1881  * exactly 30 for x=0.5, so the result is a continuous monotonic function
1882  * over the full range.
1883  */
1884  if (x <= 0.5)
1885  {
1886  volatile float8 asin_x = asin(x);
1887 
1888  return (asin_x / asin_0_5) * 30.0;
1889  }
1890  else
1891  {
1892  volatile float8 acos_x = acos(x);
1893 
1894  return 90.0 - (acos_x / acos_0_5) * 60.0;
1895  }
1896 }
1897 
1898 
1899 /*
1900  * acosd_q1 - returns the inverse cosine of x in degrees, for x in
1901  * the range [0, 1]. The result is an angle in the
1902  * first quadrant --- [0, 90] degrees.
1903  *
1904  * For the 3 special case inputs (0, 0.5 and 1), this
1905  * function will return exact values (0, 60 and 90
1906  * degrees respectively).
1907  */
1908 static double
1909 acosd_q1(double x)
1910 {
1911  /*
1912  * Stitch together inverse sine and cosine functions for the ranges [0,
1913  * 0.5] and (0.5, 1]. Each expression below is guaranteed to return
1914  * exactly 60 for x=0.5, so the result is a continuous monotonic function
1915  * over the full range.
1916  */
1917  if (x <= 0.5)
1918  {
1919  volatile float8 asin_x = asin(x);
1920 
1921  return 90.0 - (asin_x / asin_0_5) * 30.0;
1922  }
1923  else
1924  {
1925  volatile float8 acos_x = acos(x);
1926 
1927  return (acos_x / acos_0_5) * 60.0;
1928  }
1929 }
1930 
1931 
1932 /*
1933  * dacosd - returns the arccos of arg1 (degrees)
1934  */
1935 Datum
1937 {
1938  float8 arg1 = PG_GETARG_FLOAT8(0);
1939  float8 result;
1940 
1941  /* Per the POSIX spec, return NaN if the input is NaN */
1942  if (isnan(arg1))
1944 
1946 
1947  /*
1948  * The principal branch of the inverse cosine function maps values in the
1949  * range [-1, 1] to values in the range [0, 180], so we should reject any
1950  * inputs outside that range and the result will always be finite.
1951  */
1952  if (arg1 < -1.0 || arg1 > 1.0)
1953  ereport(ERROR,
1954  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1955  errmsg("input is out of range")));
1956 
1957  if (arg1 >= 0.0)
1958  result = acosd_q1(arg1);
1959  else
1960  result = 90.0 + asind_q1(-arg1);
1961 
1962  CHECKFLOATVAL(result, false, true);
1963  PG_RETURN_FLOAT8(result);
1964 }
1965 
1966 
1967 /*
1968  * dasind - returns the arcsin of arg1 (degrees)
1969  */
1970 Datum
1972 {
1973  float8 arg1 = PG_GETARG_FLOAT8(0);
1974  float8 result;
1975 
1976  /* Per the POSIX spec, return NaN if the input is NaN */
1977  if (isnan(arg1))
1979 
1981 
1982  /*
1983  * The principal branch of the inverse sine function maps values in the
1984  * range [-1, 1] to values in the range [-90, 90], so we should reject any
1985  * inputs outside that range and the result will always be finite.
1986  */
1987  if (arg1 < -1.0 || arg1 > 1.0)
1988  ereport(ERROR,
1989  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1990  errmsg("input is out of range")));
1991 
1992  if (arg1 >= 0.0)
1993  result = asind_q1(arg1);
1994  else
1995  result = -asind_q1(-arg1);
1996 
1997  CHECKFLOATVAL(result, false, true);
1998  PG_RETURN_FLOAT8(result);
1999 }
2000 
2001 
2002 /*
2003  * datand - returns the arctan of arg1 (degrees)
2004  */
2005 Datum
2007 {
2008  float8 arg1 = PG_GETARG_FLOAT8(0);
2009  float8 result;
2010  volatile float8 atan_arg1;
2011 
2012  /* Per the POSIX spec, return NaN if the input is NaN */
2013  if (isnan(arg1))
2015 
2017 
2018  /*
2019  * The principal branch of the inverse tangent function maps all inputs to
2020  * values in the range [-90, 90], so the result should always be finite,
2021  * even if the input is infinite. Additionally, we take care to ensure
2022  * than when arg1 is 1, the result is exactly 45.
2023  */
2024  atan_arg1 = atan(arg1);
2025  result = (atan_arg1 / atan_1_0) * 45.0;
2026 
2027  CHECKFLOATVAL(result, false, true);
2028  PG_RETURN_FLOAT8(result);
2029 }
2030 
2031 
2032 /*
2033  * atan2d - returns the arctan of arg1/arg2 (degrees)
2034  */
2035 Datum
2037 {
2038  float8 arg1 = PG_GETARG_FLOAT8(0);
2039  float8 arg2 = PG_GETARG_FLOAT8(1);
2040  float8 result;
2041  volatile float8 atan2_arg1_arg2;
2042 
2043  /* Per the POSIX spec, return NaN if either input is NaN */
2044  if (isnan(arg1) || isnan(arg2))
2046 
2048 
2049  /*
2050  * atan2d maps all inputs to values in the range [-180, 180], so the
2051  * result should always be finite, even if the inputs are infinite.
2052  *
2053  * Note: this coding assumes that atan(1.0) is a suitable scaling constant
2054  * to get an exact result from atan2(). This might well fail on us at
2055  * some point, requiring us to decide exactly what inputs we think we're
2056  * going to guarantee an exact result for.
2057  */
2058  atan2_arg1_arg2 = atan2(arg1, arg2);
2059  result = (atan2_arg1_arg2 / atan_1_0) * 45.0;
2060 
2061  CHECKFLOATVAL(result, false, true);
2062  PG_RETURN_FLOAT8(result);
2063 }
2064 
2065 
2066 /*
2067  * sind_0_to_30 - returns the sine of an angle that lies between 0 and
2068  * 30 degrees. This will return exactly 0 when x is 0,
2069  * and exactly 0.5 when x is 30 degrees.
2070  */
2071 static double
2072 sind_0_to_30(double x)
2073 {
2074  volatile float8 sin_x = sin(x * RADIANS_PER_DEGREE);
2075 
2076  return (sin_x / sin_30) / 2.0;
2077 }
2078 
2079 
2080 /*
2081  * cosd_0_to_60 - returns the cosine of an angle that lies between 0
2082  * and 60 degrees. This will return exactly 1 when x
2083  * is 0, and exactly 0.5 when x is 60 degrees.
2084  */
2085 static double
2086 cosd_0_to_60(double x)
2087 {
2088  volatile float8 one_minus_cos_x = 1.0 - cos(x * RADIANS_PER_DEGREE);
2089 
2090  return 1.0 - (one_minus_cos_x / one_minus_cos_60) / 2.0;
2091 }
2092 
2093 
2094 /*
2095  * sind_q1 - returns the sine of an angle in the first quadrant
2096  * (0 to 90 degrees).
2097  */
2098 static double
2099 sind_q1(double x)
2100 {
2101  /*
2102  * Stitch together the sine and cosine functions for the ranges [0, 30]
2103  * and (30, 90]. These guarantee to return exact answers at their
2104  * endpoints, so the overall result is a continuous monotonic function
2105  * that gives exact results when x = 0, 30 and 90 degrees.
2106  */
2107  if (x <= 30.0)
2108  return sind_0_to_30(x);
2109  else
2110  return cosd_0_to_60(90.0 - x);
2111 }
2112 
2113 
2114 /*
2115  * cosd_q1 - returns the cosine of an angle in the first quadrant
2116  * (0 to 90 degrees).
2117  */
2118 static double
2119 cosd_q1(double x)
2120 {
2121  /*
2122  * Stitch together the sine and cosine functions for the ranges [0, 60]
2123  * and (60, 90]. These guarantee to return exact answers at their
2124  * endpoints, so the overall result is a continuous monotonic function
2125  * that gives exact results when x = 0, 60 and 90 degrees.
2126  */
2127  if (x <= 60.0)
2128  return cosd_0_to_60(x);
2129  else
2130  return sind_0_to_30(90.0 - x);
2131 }
2132 
2133 
2134 /*
2135  * dcosd - returns the cosine of arg1 (degrees)
2136  */
2137 Datum
2139 {
2140  float8 arg1 = PG_GETARG_FLOAT8(0);
2141  float8 result;
2142  int sign = 1;
2143 
2144  /*
2145  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2146  * if the input is infinite.
2147  */
2148  if (isnan(arg1))
2150 
2151  if (isinf(arg1))
2152  ereport(ERROR,
2153  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2154  errmsg("input is out of range")));
2155 
2157 
2158  /* Reduce the range of the input to [0,90] degrees */
2159  arg1 = fmod(arg1, 360.0);
2160 
2161  if (arg1 < 0.0)
2162  {
2163  /* cosd(-x) = cosd(x) */
2164  arg1 = -arg1;
2165  }
2166 
2167  if (arg1 > 180.0)
2168  {
2169  /* cosd(360-x) = cosd(x) */
2170  arg1 = 360.0 - arg1;
2171  }
2172 
2173  if (arg1 > 90.0)
2174  {
2175  /* cosd(180-x) = -cosd(x) */
2176  arg1 = 180.0 - arg1;
2177  sign = -sign;
2178  }
2179 
2180  result = sign * cosd_q1(arg1);
2181 
2182  CHECKFLOATVAL(result, false, true);
2183  PG_RETURN_FLOAT8(result);
2184 }
2185 
2186 
2187 /*
2188  * dcotd - returns the cotangent of arg1 (degrees)
2189  */
2190 Datum
2192 {
2193  float8 arg1 = PG_GETARG_FLOAT8(0);
2194  float8 result;
2195  volatile float8 cot_arg1;
2196  int sign = 1;
2197 
2198  /*
2199  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2200  * if the input is infinite.
2201  */
2202  if (isnan(arg1))
2204 
2205  if (isinf(arg1))
2206  ereport(ERROR,
2207  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2208  errmsg("input is out of range")));
2209 
2211 
2212  /* Reduce the range of the input to [0,90] degrees */
2213  arg1 = fmod(arg1, 360.0);
2214 
2215  if (arg1 < 0.0)
2216  {
2217  /* cotd(-x) = -cotd(x) */
2218  arg1 = -arg1;
2219  sign = -sign;
2220  }
2221 
2222  if (arg1 > 180.0)
2223  {
2224  /* cotd(360-x) = -cotd(x) */
2225  arg1 = 360.0 - arg1;
2226  sign = -sign;
2227  }
2228 
2229  if (arg1 > 90.0)
2230  {
2231  /* cotd(180-x) = -cotd(x) */
2232  arg1 = 180.0 - arg1;
2233  sign = -sign;
2234  }
2235 
2236  cot_arg1 = cosd_q1(arg1) / sind_q1(arg1);
2237  result = sign * (cot_arg1 / cot_45);
2238 
2239  /*
2240  * On some machines we get cotd(270) = minus zero, but this isn't always
2241  * true. For portability, and because the user constituency for this
2242  * function probably doesn't want minus zero, force it to plain zero.
2243  */
2244  if (result == 0.0)
2245  result = 0.0;
2246 
2247  CHECKFLOATVAL(result, true /* cotd(0) == Inf */ , true);
2248  PG_RETURN_FLOAT8(result);
2249 }
2250 
2251 
2252 /*
2253  * dsind - returns the sine of arg1 (degrees)
2254  */
2255 Datum
2257 {
2258  float8 arg1 = PG_GETARG_FLOAT8(0);
2259  float8 result;
2260  int sign = 1;
2261 
2262  /*
2263  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2264  * if the input is infinite.
2265  */
2266  if (isnan(arg1))
2268 
2269  if (isinf(arg1))
2270  ereport(ERROR,
2271  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2272  errmsg("input is out of range")));
2273 
2275 
2276  /* Reduce the range of the input to [0,90] degrees */
2277  arg1 = fmod(arg1, 360.0);
2278 
2279  if (arg1 < 0.0)
2280  {
2281  /* sind(-x) = -sind(x) */
2282  arg1 = -arg1;
2283  sign = -sign;
2284  }
2285 
2286  if (arg1 > 180.0)
2287  {
2288  /* sind(360-x) = -sind(x) */
2289  arg1 = 360.0 - arg1;
2290  sign = -sign;
2291  }
2292 
2293  if (arg1 > 90.0)
2294  {
2295  /* sind(180-x) = sind(x) */
2296  arg1 = 180.0 - arg1;
2297  }
2298 
2299  result = sign * sind_q1(arg1);
2300 
2301  CHECKFLOATVAL(result, false, true);
2302  PG_RETURN_FLOAT8(result);
2303 }
2304 
2305 
2306 /*
2307  * dtand - returns the tangent of arg1 (degrees)
2308  */
2309 Datum
2311 {
2312  float8 arg1 = PG_GETARG_FLOAT8(0);
2313  float8 result;
2314  volatile float8 tan_arg1;
2315  int sign = 1;
2316 
2317  /*
2318  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2319  * if the input is infinite.
2320  */
2321  if (isnan(arg1))
2323 
2324  if (isinf(arg1))
2325  ereport(ERROR,
2326  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2327  errmsg("input is out of range")));
2328 
2330 
2331  /* Reduce the range of the input to [0,90] degrees */
2332  arg1 = fmod(arg1, 360.0);
2333 
2334  if (arg1 < 0.0)
2335  {
2336  /* tand(-x) = -tand(x) */
2337  arg1 = -arg1;
2338  sign = -sign;
2339  }
2340 
2341  if (arg1 > 180.0)
2342  {
2343  /* tand(360-x) = -tand(x) */
2344  arg1 = 360.0 - arg1;
2345  sign = -sign;
2346  }
2347 
2348  if (arg1 > 90.0)
2349  {
2350  /* tand(180-x) = -tand(x) */
2351  arg1 = 180.0 - arg1;
2352  sign = -sign;
2353  }
2354 
2355  tan_arg1 = sind_q1(arg1) / cosd_q1(arg1);
2356  result = sign * (tan_arg1 / tan_45);
2357 
2358  /*
2359  * On some machines we get tand(180) = minus zero, but this isn't always
2360  * true. For portability, and because the user constituency for this
2361  * function probably doesn't want minus zero, force it to plain zero.
2362  */
2363  if (result == 0.0)
2364  result = 0.0;
2365 
2366  CHECKFLOATVAL(result, true /* tand(90) == Inf */ , true);
2367  PG_RETURN_FLOAT8(result);
2368 }
2369 
2370 
2371 /*
2372  * degrees - returns degrees converted from radians
2373  */
2374 Datum
2376 {
2377  float8 arg1 = PG_GETARG_FLOAT8(0);
2378  float8 result;
2379 
2380  result = arg1 / RADIANS_PER_DEGREE;
2381 
2382  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
2383  PG_RETURN_FLOAT8(result);
2384 }
2385 
2386 
2387 /*
2388  * dpi - returns the constant PI
2389  */
2390 Datum
2392 {
2394 }
2395 
2396 
2397 /*
2398  * radians - returns radians converted from degrees
2399  */
2400 Datum
2402 {
2403  float8 arg1 = PG_GETARG_FLOAT8(0);
2404  float8 result;
2405 
2406  result = arg1 * RADIANS_PER_DEGREE;
2407 
2408  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
2409  PG_RETURN_FLOAT8(result);
2410 }
2411 
2412 
2413 /*
2414  * drandom - returns a random number
2415  */
2416 Datum
2418 {
2419  float8 result;
2420 
2421  /* result [0.0 - 1.0) */
2422  result = (double) random() / ((double) MAX_RANDOM_VALUE + 1);
2423 
2424  PG_RETURN_FLOAT8(result);
2425 }
2426 
2427 
2428 /*
2429  * setseed - set seed for the random number generator
2430  */
2431 Datum
2433 {
2434  float8 seed = PG_GETARG_FLOAT8(0);
2435  int iseed;
2436 
2437  if (seed < -1 || seed > 1)
2438  elog(ERROR, "setseed parameter %f out of range [-1,1]", seed);
2439 
2440  iseed = (int) (seed * MAX_RANDOM_VALUE);
2441  srandom((unsigned int) iseed);
2442 
2443  PG_RETURN_VOID();
2444 }
2445 
2446 
2447 
2448 /*
2449  * =========================
2450  * FLOAT AGGREGATE OPERATORS
2451  * =========================
2452  *
2453  * float8_accum - accumulate for AVG(), variance aggregates, etc.
2454  * float4_accum - same, but input data is float4
2455  * float8_avg - produce final result for float AVG()
2456  * float8_var_samp - produce final result for float VAR_SAMP()
2457  * float8_var_pop - produce final result for float VAR_POP()
2458  * float8_stddev_samp - produce final result for float STDDEV_SAMP()
2459  * float8_stddev_pop - produce final result for float STDDEV_POP()
2460  *
2461  * The transition datatype for all these aggregates is a 3-element array
2462  * of float8, holding the values N, sum(X), sum(X*X) in that order.
2463  *
2464  * Note that we represent N as a float to avoid having to build a special
2465  * datatype. Given a reasonable floating-point implementation, there should
2466  * be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the
2467  * user will have doubtless lost interest anyway...)
2468  */
2469 
2470 static float8 *
2471 check_float8_array(ArrayType *transarray, const char *caller, int n)
2472 {
2473  /*
2474  * We expect the input to be an N-element float array; verify that. We
2475  * don't need to use deconstruct_array() since the array data is just
2476  * going to look like a C array of N float8 values.
2477  */
2478  if (ARR_NDIM(transarray) != 1 ||
2479  ARR_DIMS(transarray)[0] != n ||
2480  ARR_HASNULL(transarray) ||
2481  ARR_ELEMTYPE(transarray) != FLOAT8OID)
2482  elog(ERROR, "%s: expected %d-element float8 array", caller, n);
2483  return (float8 *) ARR_DATA_PTR(transarray);
2484 }
2485 
2486 /*
2487  * float8_combine
2488  *
2489  * An aggregate combine function used to combine two 3 fields
2490  * aggregate transition data into a single transition data.
2491  * This function is used only in two stage aggregation and
2492  * shouldn't be called outside aggregate context.
2493  */
2494 Datum
2496 {
2497  ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
2498  ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
2499  float8 *transvalues1;
2500  float8 *transvalues2;
2501  float8 N,
2502  sumX,
2503  sumX2;
2504 
2505  if (!AggCheckCallContext(fcinfo, NULL))
2506  elog(ERROR, "aggregate function called in non-aggregate context");
2507 
2508  transvalues1 = check_float8_array(transarray1, "float8_combine", 3);
2509  N = transvalues1[0];
2510  sumX = transvalues1[1];
2511  sumX2 = transvalues1[2];
2512 
2513  transvalues2 = check_float8_array(transarray2, "float8_combine", 3);
2514 
2515  N += transvalues2[0];
2516  sumX += transvalues2[1];
2517  CHECKFLOATVAL(sumX, isinf(transvalues1[1]) || isinf(transvalues2[1]),
2518  true);
2519  sumX2 += transvalues2[2];
2520  CHECKFLOATVAL(sumX2, isinf(transvalues1[2]) || isinf(transvalues2[2]),
2521  true);
2522 
2523  transvalues1[0] = N;
2524  transvalues1[1] = sumX;
2525  transvalues1[2] = sumX2;
2526 
2527  PG_RETURN_ARRAYTYPE_P(transarray1);
2528 }
2529 
2530 Datum
2532 {
2533  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2535  float8 *transvalues;
2536  float8 N,
2537  sumX,
2538  sumX2;
2539 
2540  transvalues = check_float8_array(transarray, "float8_accum", 3);
2541  N = transvalues[0];
2542  sumX = transvalues[1];
2543  sumX2 = transvalues[2];
2544 
2545  N += 1.0;
2546  sumX += newval;
2547  CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
2548  sumX2 += newval * newval;
2549  CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
2550 
2551  /*
2552  * If we're invoked as an aggregate, we can cheat and modify our first
2553  * parameter in-place to reduce palloc overhead. Otherwise we construct a
2554  * new array with the updated transition data and return it.
2555  */
2556  if (AggCheckCallContext(fcinfo, NULL))
2557  {
2558  transvalues[0] = N;
2559  transvalues[1] = sumX;
2560  transvalues[2] = sumX2;
2561 
2562  PG_RETURN_ARRAYTYPE_P(transarray);
2563  }
2564  else
2565  {
2566  Datum transdatums[3];
2567  ArrayType *result;
2568 
2569  transdatums[0] = Float8GetDatumFast(N);
2570  transdatums[1] = Float8GetDatumFast(sumX);
2571  transdatums[2] = Float8GetDatumFast(sumX2);
2572 
2573  result = construct_array(transdatums, 3,
2574  FLOAT8OID,
2575  sizeof(float8), FLOAT8PASSBYVAL, 'd');
2576 
2577  PG_RETURN_ARRAYTYPE_P(result);
2578  }
2579 }
2580 
2581 Datum
2583 {
2584  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2585 
2586  /* do computations as float8 */
2588  float8 *transvalues;
2589  float8 N,
2590  sumX,
2591  sumX2;
2592 
2593  transvalues = check_float8_array(transarray, "float4_accum", 3);
2594  N = transvalues[0];
2595  sumX = transvalues[1];
2596  sumX2 = transvalues[2];
2597 
2598  N += 1.0;
2599  sumX += newval;
2600  CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
2601  sumX2 += newval * newval;
2602  CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
2603 
2604  /*
2605  * If we're invoked as an aggregate, we can cheat and modify our first
2606  * parameter in-place to reduce palloc overhead. Otherwise we construct a
2607  * new array with the updated transition data and return it.
2608  */
2609  if (AggCheckCallContext(fcinfo, NULL))
2610  {
2611  transvalues[0] = N;
2612  transvalues[1] = sumX;
2613  transvalues[2] = sumX2;
2614 
2615  PG_RETURN_ARRAYTYPE_P(transarray);
2616  }
2617  else
2618  {
2619  Datum transdatums[3];
2620  ArrayType *result;
2621 
2622  transdatums[0] = Float8GetDatumFast(N);
2623  transdatums[1] = Float8GetDatumFast(sumX);
2624  transdatums[2] = Float8GetDatumFast(sumX2);
2625 
2626  result = construct_array(transdatums, 3,
2627  FLOAT8OID,
2628  sizeof(float8), FLOAT8PASSBYVAL, 'd');
2629 
2630  PG_RETURN_ARRAYTYPE_P(result);
2631  }
2632 }
2633 
2634 Datum
2636 {
2637  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2638  float8 *transvalues;
2639  float8 N,
2640  sumX;
2641 
2642  transvalues = check_float8_array(transarray, "float8_avg", 3);
2643  N = transvalues[0];
2644  sumX = transvalues[1];
2645  /* ignore sumX2 */
2646 
2647  /* SQL defines AVG of no values to be NULL */
2648  if (N == 0.0)
2649  PG_RETURN_NULL();
2650 
2651  PG_RETURN_FLOAT8(sumX / N);
2652 }
2653 
2654 Datum
2656 {
2657  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2658  float8 *transvalues;
2659  float8 N,
2660  sumX,
2661  sumX2,
2662  numerator;
2663 
2664  transvalues = check_float8_array(transarray, "float8_var_pop", 3);
2665  N = transvalues[0];
2666  sumX = transvalues[1];
2667  sumX2 = transvalues[2];
2668 
2669  /* Population variance is undefined when N is 0, so return NULL */
2670  if (N == 0.0)
2671  PG_RETURN_NULL();
2672 
2673  numerator = N * sumX2 - sumX * sumX;
2674  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2675 
2676  /* Watch out for roundoff error producing a negative numerator */
2677  if (numerator <= 0.0)
2678  PG_RETURN_FLOAT8(0.0);
2679 
2680  PG_RETURN_FLOAT8(numerator / (N * N));
2681 }
2682 
2683 Datum
2685 {
2686  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2687  float8 *transvalues;
2688  float8 N,
2689  sumX,
2690  sumX2,
2691  numerator;
2692 
2693  transvalues = check_float8_array(transarray, "float8_var_samp", 3);
2694  N = transvalues[0];
2695  sumX = transvalues[1];
2696  sumX2 = transvalues[2];
2697 
2698  /* Sample variance is undefined when N is 0 or 1, so return NULL */
2699  if (N <= 1.0)
2700  PG_RETURN_NULL();
2701 
2702  numerator = N * sumX2 - sumX * sumX;
2703  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2704 
2705  /* Watch out for roundoff error producing a negative numerator */
2706  if (numerator <= 0.0)
2707  PG_RETURN_FLOAT8(0.0);
2708 
2709  PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
2710 }
2711 
2712 Datum
2714 {
2715  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2716  float8 *transvalues;
2717  float8 N,
2718  sumX,
2719  sumX2,
2720  numerator;
2721 
2722  transvalues = check_float8_array(transarray, "float8_stddev_pop", 3);
2723  N = transvalues[0];
2724  sumX = transvalues[1];
2725  sumX2 = transvalues[2];
2726 
2727  /* Population stddev is undefined when N is 0, so return NULL */
2728  if (N == 0.0)
2729  PG_RETURN_NULL();
2730 
2731  numerator = N * sumX2 - sumX * sumX;
2732  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2733 
2734  /* Watch out for roundoff error producing a negative numerator */
2735  if (numerator <= 0.0)
2736  PG_RETURN_FLOAT8(0.0);
2737 
2738  PG_RETURN_FLOAT8(sqrt(numerator / (N * N)));
2739 }
2740 
2741 Datum
2743 {
2744  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2745  float8 *transvalues;
2746  float8 N,
2747  sumX,
2748  sumX2,
2749  numerator;
2750 
2751  transvalues = check_float8_array(transarray, "float8_stddev_samp", 3);
2752  N = transvalues[0];
2753  sumX = transvalues[1];
2754  sumX2 = transvalues[2];
2755 
2756  /* Sample stddev is undefined when N is 0 or 1, so return NULL */
2757  if (N <= 1.0)
2758  PG_RETURN_NULL();
2759 
2760  numerator = N * sumX2 - sumX * sumX;
2761  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2762 
2763  /* Watch out for roundoff error producing a negative numerator */
2764  if (numerator <= 0.0)
2765  PG_RETURN_FLOAT8(0.0);
2766 
2767  PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));
2768 }
2769 
2770 /*
2771  * =========================
2772  * SQL2003 BINARY AGGREGATES
2773  * =========================
2774  *
2775  * The transition datatype for all these aggregates is a 6-element array of
2776  * float8, holding the values N, sum(X), sum(X*X), sum(Y), sum(Y*Y), sum(X*Y)
2777  * in that order. Note that Y is the first argument to the aggregates!
2778  *
2779  * It might seem attractive to optimize this by having multiple accumulator
2780  * functions that only calculate the sums actually needed. But on most
2781  * modern machines, a couple of extra floating-point multiplies will be
2782  * insignificant compared to the other per-tuple overhead, so I've chosen
2783  * to minimize code space instead.
2784  */
2785 
2786 Datum
2788 {
2789  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2790  float8 newvalY = PG_GETARG_FLOAT8(1);
2791  float8 newvalX = PG_GETARG_FLOAT8(2);
2792  float8 *transvalues;
2793  float8 N,
2794  sumX,
2795  sumX2,
2796  sumY,
2797  sumY2,
2798  sumXY;
2799 
2800  transvalues = check_float8_array(transarray, "float8_regr_accum", 6);
2801  N = transvalues[0];
2802  sumX = transvalues[1];
2803  sumX2 = transvalues[2];
2804  sumY = transvalues[3];
2805  sumY2 = transvalues[4];
2806  sumXY = transvalues[5];
2807 
2808  N += 1.0;
2809  sumX += newvalX;
2810  CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newvalX), true);
2811  sumX2 += newvalX * newvalX;
2812  CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newvalX), true);
2813  sumY += newvalY;
2814  CHECKFLOATVAL(sumY, isinf(transvalues[3]) || isinf(newvalY), true);
2815  sumY2 += newvalY * newvalY;
2816  CHECKFLOATVAL(sumY2, isinf(transvalues[4]) || isinf(newvalY), true);
2817  sumXY += newvalX * newvalY;
2818  CHECKFLOATVAL(sumXY, isinf(transvalues[5]) || isinf(newvalX) ||
2819  isinf(newvalY), true);
2820 
2821  /*
2822  * If we're invoked as an aggregate, we can cheat and modify our first
2823  * parameter in-place to reduce palloc overhead. Otherwise we construct a
2824  * new array with the updated transition data and return it.
2825  */
2826  if (AggCheckCallContext(fcinfo, NULL))
2827  {
2828  transvalues[0] = N;
2829  transvalues[1] = sumX;
2830  transvalues[2] = sumX2;
2831  transvalues[3] = sumY;
2832  transvalues[4] = sumY2;
2833  transvalues[5] = sumXY;
2834 
2835  PG_RETURN_ARRAYTYPE_P(transarray);
2836  }
2837  else
2838  {
2839  Datum transdatums[6];
2840  ArrayType *result;
2841 
2842  transdatums[0] = Float8GetDatumFast(N);
2843  transdatums[1] = Float8GetDatumFast(sumX);
2844  transdatums[2] = Float8GetDatumFast(sumX2);
2845  transdatums[3] = Float8GetDatumFast(sumY);
2846  transdatums[4] = Float8GetDatumFast(sumY2);
2847  transdatums[5] = Float8GetDatumFast(sumXY);
2848 
2849  result = construct_array(transdatums, 6,
2850  FLOAT8OID,
2851  sizeof(float8), FLOAT8PASSBYVAL, 'd');
2852 
2853  PG_RETURN_ARRAYTYPE_P(result);
2854  }
2855 }
2856 
2857 /*
2858  * float8_regr_combine
2859  *
2860  * An aggregate combine function used to combine two 6 fields
2861  * aggregate transition data into a single transition data.
2862  * This function is used only in two stage aggregation and
2863  * shouldn't be called outside aggregate context.
2864  */
2865 Datum
2867 {
2868  ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
2869  ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
2870  float8 *transvalues1;
2871  float8 *transvalues2;
2872  float8 N,
2873  sumX,
2874  sumX2,
2875  sumY,
2876  sumY2,
2877  sumXY;
2878 
2879  if (!AggCheckCallContext(fcinfo, NULL))
2880  elog(ERROR, "aggregate function called in non-aggregate context");
2881 
2882  transvalues1 = check_float8_array(transarray1, "float8_regr_combine", 6);
2883  N = transvalues1[0];
2884  sumX = transvalues1[1];
2885  sumX2 = transvalues1[2];
2886  sumY = transvalues1[3];
2887  sumY2 = transvalues1[4];
2888  sumXY = transvalues1[5];
2889 
2890  transvalues2 = check_float8_array(transarray2, "float8_regr_combine", 6);
2891 
2892  N += transvalues2[0];
2893  sumX += transvalues2[1];
2894  CHECKFLOATVAL(sumX, isinf(transvalues1[1]) || isinf(transvalues2[1]),
2895  true);
2896  sumX2 += transvalues2[2];
2897  CHECKFLOATVAL(sumX2, isinf(transvalues1[2]) || isinf(transvalues2[2]),
2898  true);
2899  sumY += transvalues2[3];
2900  CHECKFLOATVAL(sumY, isinf(transvalues1[3]) || isinf(transvalues2[3]),
2901  true);
2902  sumY2 += transvalues2[4];
2903  CHECKFLOATVAL(sumY2, isinf(transvalues1[4]) || isinf(transvalues2[4]),
2904  true);
2905  sumXY += transvalues2[5];
2906  CHECKFLOATVAL(sumXY, isinf(transvalues1[5]) || isinf(transvalues2[5]),
2907  true);
2908 
2909  transvalues1[0] = N;
2910  transvalues1[1] = sumX;
2911  transvalues1[2] = sumX2;
2912  transvalues1[3] = sumY;
2913  transvalues1[4] = sumY2;
2914  transvalues1[5] = sumXY;
2915 
2916  PG_RETURN_ARRAYTYPE_P(transarray1);
2917 }
2918 
2919 
2920 Datum
2922 {
2923  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2924  float8 *transvalues;
2925  float8 N,
2926  sumX,
2927  sumX2,
2928  numerator;
2929 
2930  transvalues = check_float8_array(transarray, "float8_regr_sxx", 6);
2931  N = transvalues[0];
2932  sumX = transvalues[1];
2933  sumX2 = transvalues[2];
2934 
2935  /* if N is 0 we should return NULL */
2936  if (N < 1.0)
2937  PG_RETURN_NULL();
2938 
2939  numerator = N * sumX2 - sumX * sumX;
2940  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2941 
2942  /* Watch out for roundoff error producing a negative numerator */
2943  if (numerator <= 0.0)
2944  PG_RETURN_FLOAT8(0.0);
2945 
2946  PG_RETURN_FLOAT8(numerator / N);
2947 }
2948 
2949 Datum
2951 {
2952  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2953  float8 *transvalues;
2954  float8 N,
2955  sumY,
2956  sumY2,
2957  numerator;
2958 
2959  transvalues = check_float8_array(transarray, "float8_regr_syy", 6);
2960  N = transvalues[0];
2961  sumY = transvalues[3];
2962  sumY2 = transvalues[4];
2963 
2964  /* if N is 0 we should return NULL */
2965  if (N < 1.0)
2966  PG_RETURN_NULL();
2967 
2968  numerator = N * sumY2 - sumY * sumY;
2969  CHECKFLOATVAL(numerator, isinf(sumY2) || isinf(sumY), true);
2970 
2971  /* Watch out for roundoff error producing a negative numerator */
2972  if (numerator <= 0.0)
2973  PG_RETURN_FLOAT8(0.0);
2974 
2975  PG_RETURN_FLOAT8(numerator / N);
2976 }
2977 
2978 Datum
2980 {
2981  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2982  float8 *transvalues;
2983  float8 N,
2984  sumX,
2985  sumY,
2986  sumXY,
2987  numerator;
2988 
2989  transvalues = check_float8_array(transarray, "float8_regr_sxy", 6);
2990  N = transvalues[0];
2991  sumX = transvalues[1];
2992  sumY = transvalues[3];
2993  sumXY = transvalues[5];
2994 
2995  /* if N is 0 we should return NULL */
2996  if (N < 1.0)
2997  PG_RETURN_NULL();
2998 
2999  numerator = N * sumXY - sumX * sumY;
3000  CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
3001  isinf(sumY), true);
3002 
3003  /* A negative result is valid here */
3004 
3005  PG_RETURN_FLOAT8(numerator / N);
3006 }
3007 
3008 Datum
3010 {
3011  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3012  float8 *transvalues;
3013  float8 N,
3014  sumX;
3015 
3016  transvalues = check_float8_array(transarray, "float8_regr_avgx", 6);
3017  N = transvalues[0];
3018  sumX = transvalues[1];
3019 
3020  /* if N is 0 we should return NULL */
3021  if (N < 1.0)
3022  PG_RETURN_NULL();
3023 
3024  PG_RETURN_FLOAT8(sumX / N);
3025 }
3026 
3027 Datum
3029 {
3030  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3031  float8 *transvalues;
3032  float8 N,
3033  sumY;
3034 
3035  transvalues = check_float8_array(transarray, "float8_regr_avgy", 6);
3036  N = transvalues[0];
3037  sumY = transvalues[3];
3038 
3039  /* if N is 0 we should return NULL */
3040  if (N < 1.0)
3041  PG_RETURN_NULL();
3042 
3043  PG_RETURN_FLOAT8(sumY / N);
3044 }
3045 
3046 Datum
3048 {
3049  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3050  float8 *transvalues;
3051  float8 N,
3052  sumX,
3053  sumY,
3054  sumXY,
3055  numerator;
3056 
3057  transvalues = check_float8_array(transarray, "float8_covar_pop", 6);
3058  N = transvalues[0];
3059  sumX = transvalues[1];
3060  sumY = transvalues[3];
3061  sumXY = transvalues[5];
3062 
3063  /* if N is 0 we should return NULL */
3064  if (N < 1.0)
3065  PG_RETURN_NULL();
3066 
3067  numerator = N * sumXY - sumX * sumY;
3068  CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
3069  isinf(sumY), true);
3070 
3071  PG_RETURN_FLOAT8(numerator / (N * N));
3072 }
3073 
3074 Datum
3076 {
3077  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3078  float8 *transvalues;
3079  float8 N,
3080  sumX,
3081  sumY,
3082  sumXY,
3083  numerator;
3084 
3085  transvalues = check_float8_array(transarray, "float8_covar_samp", 6);
3086  N = transvalues[0];
3087  sumX = transvalues[1];
3088  sumY = transvalues[3];
3089  sumXY = transvalues[5];
3090 
3091  /* if N is <= 1 we should return NULL */
3092  if (N < 2.0)
3093  PG_RETURN_NULL();
3094 
3095  numerator = N * sumXY - sumX * sumY;
3096  CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
3097  isinf(sumY), true);
3098 
3099  PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
3100 }
3101 
3102 Datum
3104 {
3105  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3106  float8 *transvalues;
3107  float8 N,
3108  sumX,
3109  sumX2,
3110  sumY,
3111  sumY2,
3112  sumXY,
3113  numeratorX,
3114  numeratorY,
3115  numeratorXY;
3116 
3117  transvalues = check_float8_array(transarray, "float8_corr", 6);
3118  N = transvalues[0];
3119  sumX = transvalues[1];
3120  sumX2 = transvalues[2];
3121  sumY = transvalues[3];
3122  sumY2 = transvalues[4];
3123  sumXY = transvalues[5];
3124 
3125  /* if N is 0 we should return NULL */
3126  if (N < 1.0)
3127  PG_RETURN_NULL();
3128 
3129  numeratorX = N * sumX2 - sumX * sumX;
3130  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3131  numeratorY = N * sumY2 - sumY * sumY;
3132  CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
3133  numeratorXY = N * sumXY - sumX * sumY;
3134  CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
3135  isinf(sumY), true);
3136  if (numeratorX <= 0 || numeratorY <= 0)
3137  PG_RETURN_NULL();
3138 
3139  PG_RETURN_FLOAT8(numeratorXY / sqrt(numeratorX * numeratorY));
3140 }
3141 
3142 Datum
3144 {
3145  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3146  float8 *transvalues;
3147  float8 N,
3148  sumX,
3149  sumX2,
3150  sumY,
3151  sumY2,
3152  sumXY,
3153  numeratorX,
3154  numeratorY,
3155  numeratorXY;
3156 
3157  transvalues = check_float8_array(transarray, "float8_regr_r2", 6);
3158  N = transvalues[0];
3159  sumX = transvalues[1];
3160  sumX2 = transvalues[2];
3161  sumY = transvalues[3];
3162  sumY2 = transvalues[4];
3163  sumXY = transvalues[5];
3164 
3165  /* if N is 0 we should return NULL */
3166  if (N < 1.0)
3167  PG_RETURN_NULL();
3168 
3169  numeratorX = N * sumX2 - sumX * sumX;
3170  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3171  numeratorY = N * sumY2 - sumY * sumY;
3172  CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
3173  numeratorXY = N * sumXY - sumX * sumY;
3174  CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
3175  isinf(sumY), true);
3176  if (numeratorX <= 0)
3177  PG_RETURN_NULL();
3178  /* per spec, horizontal line produces 1.0 */
3179  if (numeratorY <= 0)
3180  PG_RETURN_FLOAT8(1.0);
3181 
3182  PG_RETURN_FLOAT8((numeratorXY * numeratorXY) /
3183  (numeratorX * numeratorY));
3184 }
3185 
3186 Datum
3188 {
3189  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3190  float8 *transvalues;
3191  float8 N,
3192  sumX,
3193  sumX2,
3194  sumY,
3195  sumXY,
3196  numeratorX,
3197  numeratorXY;
3198 
3199  transvalues = check_float8_array(transarray, "float8_regr_slope", 6);
3200  N = transvalues[0];
3201  sumX = transvalues[1];
3202  sumX2 = transvalues[2];
3203  sumY = transvalues[3];
3204  sumXY = transvalues[5];
3205 
3206  /* if N is 0 we should return NULL */
3207  if (N < 1.0)
3208  PG_RETURN_NULL();
3209 
3210  numeratorX = N * sumX2 - sumX * sumX;
3211  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3212  numeratorXY = N * sumXY - sumX * sumY;
3213  CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
3214  isinf(sumY), true);
3215  if (numeratorX <= 0)
3216  PG_RETURN_NULL();
3217 
3218  PG_RETURN_FLOAT8(numeratorXY / numeratorX);
3219 }
3220 
3221 Datum
3223 {
3224  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3225  float8 *transvalues;
3226  float8 N,
3227  sumX,
3228  sumX2,
3229  sumY,
3230  sumXY,
3231  numeratorX,
3232  numeratorXXY;
3233 
3234  transvalues = check_float8_array(transarray, "float8_regr_intercept", 6);
3235  N = transvalues[0];
3236  sumX = transvalues[1];
3237  sumX2 = transvalues[2];
3238  sumY = transvalues[3];
3239  sumXY = transvalues[5];
3240 
3241  /* if N is 0 we should return NULL */
3242  if (N < 1.0)
3243  PG_RETURN_NULL();
3244 
3245  numeratorX = N * sumX2 - sumX * sumX;
3246  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3247  numeratorXXY = sumY * sumX2 - sumX * sumXY;
3248  CHECKFLOATVAL(numeratorXXY, isinf(sumY) || isinf(sumX2) ||
3249  isinf(sumX) || isinf(sumXY), true);
3250  if (numeratorX <= 0)
3251  PG_RETURN_NULL();
3252 
3253  PG_RETURN_FLOAT8(numeratorXXY / numeratorX);
3254 }
3255 
3256 
3257 /*
3258  * ====================================
3259  * MIXED-PRECISION ARITHMETIC OPERATORS
3260  * ====================================
3261  */
3262 
3263 /*
3264  * float48pl - returns arg1 + arg2
3265  * float48mi - returns arg1 - arg2
3266  * float48mul - returns arg1 * arg2
3267  * float48div - returns arg1 / arg2
3268  */
3269 Datum
3271 {
3272  float4 arg1 = PG_GETARG_FLOAT4(0);
3273  float8 arg2 = PG_GETARG_FLOAT8(1);
3274  float8 result;
3275 
3276  result = arg1 + arg2;
3277  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3278  PG_RETURN_FLOAT8(result);
3279 }
3280 
3281 Datum
3283 {
3284  float4 arg1 = PG_GETARG_FLOAT4(0);
3285  float8 arg2 = PG_GETARG_FLOAT8(1);
3286  float8 result;
3287 
3288  result = arg1 - arg2;
3289  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3290  PG_RETURN_FLOAT8(result);
3291 }
3292 
3293 Datum
3295 {
3296  float4 arg1 = PG_GETARG_FLOAT4(0);
3297  float8 arg2 = PG_GETARG_FLOAT8(1);
3298  float8 result;
3299 
3300  result = arg1 * arg2;
3301  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
3302  arg1 == 0 || arg2 == 0);
3303  PG_RETURN_FLOAT8(result);
3304 }
3305 
3306 Datum
3308 {
3309  float4 arg1 = PG_GETARG_FLOAT4(0);
3310  float8 arg2 = PG_GETARG_FLOAT8(1);
3311  float8 result;
3312 
3313  if (arg2 == 0.0)
3314  ereport(ERROR,
3315  (errcode(ERRCODE_DIVISION_BY_ZERO),
3316  errmsg("division by zero")));
3317 
3318  result = arg1 / arg2;
3319  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
3320  PG_RETURN_FLOAT8(result);
3321 }
3322 
3323 /*
3324  * float84pl - returns arg1 + arg2
3325  * float84mi - returns arg1 - arg2
3326  * float84mul - returns arg1 * arg2
3327  * float84div - returns arg1 / arg2
3328  */
3329 Datum
3331 {
3332  float8 arg1 = PG_GETARG_FLOAT8(0);
3333  float4 arg2 = PG_GETARG_FLOAT4(1);
3334  float8 result;
3335 
3336  result = arg1 + arg2;
3337 
3338  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3339  PG_RETURN_FLOAT8(result);
3340 }
3341 
3342 Datum
3344 {
3345  float8 arg1 = PG_GETARG_FLOAT8(0);
3346  float4 arg2 = PG_GETARG_FLOAT4(1);
3347  float8 result;
3348 
3349  result = arg1 - arg2;
3350 
3351  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3352  PG_RETURN_FLOAT8(result);
3353 }
3354 
3355 Datum
3357 {
3358  float8 arg1 = PG_GETARG_FLOAT8(0);
3359  float4 arg2 = PG_GETARG_FLOAT4(1);
3360  float8 result;
3361 
3362  result = arg1 * arg2;
3363 
3364  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
3365  arg1 == 0 || arg2 == 0);
3366  PG_RETURN_FLOAT8(result);
3367 }
3368 
3369 Datum
3371 {
3372  float8 arg1 = PG_GETARG_FLOAT8(0);
3373  float4 arg2 = PG_GETARG_FLOAT4(1);
3374  float8 result;
3375 
3376  if (arg2 == 0.0)
3377  ereport(ERROR,
3378  (errcode(ERRCODE_DIVISION_BY_ZERO),
3379  errmsg("division by zero")));
3380 
3381  result = arg1 / arg2;
3382 
3383  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
3384  PG_RETURN_FLOAT8(result);
3385 }
3386 
3387 /*
3388  * ====================
3389  * COMPARISON OPERATORS
3390  * ====================
3391  */
3392 
3393 /*
3394  * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
3395  */
3396 Datum
3398 {
3399  float4 arg1 = PG_GETARG_FLOAT4(0);
3400  float8 arg2 = PG_GETARG_FLOAT8(1);
3401 
3402  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
3403 }
3404 
3405 Datum
3407 {
3408  float4 arg1 = PG_GETARG_FLOAT4(0);
3409  float8 arg2 = PG_GETARG_FLOAT8(1);
3410 
3411  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
3412 }
3413 
3414 Datum
3416 {
3417  float4 arg1 = PG_GETARG_FLOAT4(0);
3418  float8 arg2 = PG_GETARG_FLOAT8(1);
3419 
3420  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
3421 }
3422 
3423 Datum
3425 {
3426  float4 arg1 = PG_GETARG_FLOAT4(0);
3427  float8 arg2 = PG_GETARG_FLOAT8(1);
3428 
3429  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
3430 }
3431 
3432 Datum
3434 {
3435  float4 arg1 = PG_GETARG_FLOAT4(0);
3436  float8 arg2 = PG_GETARG_FLOAT8(1);
3437 
3438  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
3439 }
3440 
3441 Datum
3443 {
3444  float4 arg1 = PG_GETARG_FLOAT4(0);
3445  float8 arg2 = PG_GETARG_FLOAT8(1);
3446 
3447  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
3448 }
3449 
3450 /*
3451  * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
3452  */
3453 Datum
3455 {
3456  float8 arg1 = PG_GETARG_FLOAT8(0);
3457  float4 arg2 = PG_GETARG_FLOAT4(1);
3458 
3459  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
3460 }
3461 
3462 Datum
3464 {
3465  float8 arg1 = PG_GETARG_FLOAT8(0);
3466  float4 arg2 = PG_GETARG_FLOAT4(1);
3467 
3468  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
3469 }
3470 
3471 Datum
3473 {
3474  float8 arg1 = PG_GETARG_FLOAT8(0);
3475  float4 arg2 = PG_GETARG_FLOAT4(1);
3476 
3477  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
3478 }
3479 
3480 Datum
3482 {
3483  float8 arg1 = PG_GETARG_FLOAT8(0);
3484  float4 arg2 = PG_GETARG_FLOAT4(1);
3485 
3486  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
3487 }
3488 
3489 Datum
3491 {
3492  float8 arg1 = PG_GETARG_FLOAT8(0);
3493  float4 arg2 = PG_GETARG_FLOAT4(1);
3494 
3495  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
3496 }
3497 
3498 Datum
3500 {
3501  float8 arg1 = PG_GETARG_FLOAT8(0);
3502  float4 arg2 = PG_GETARG_FLOAT4(1);
3503 
3504  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
3505 }
3506 
3507 /*
3508  * Implements the float8 version of the width_bucket() function
3509  * defined by SQL2003. See also width_bucket_numeric().
3510  *
3511  * 'bound1' and 'bound2' are the lower and upper bounds of the
3512  * histogram's range, respectively. 'count' is the number of buckets
3513  * in the histogram. width_bucket() returns an integer indicating the
3514  * bucket number that 'operand' belongs to in an equiwidth histogram
3515  * with the specified characteristics. An operand smaller than the
3516  * lower bound is assigned to bucket 0. An operand greater than the
3517  * upper bound is assigned to an additional bucket (with number
3518  * count+1). We don't allow "NaN" for any of the float8 inputs, and we
3519  * don't allow either of the histogram bounds to be +/- infinity.
3520  */
3521 Datum
3523 {
3524  float8 operand = PG_GETARG_FLOAT8(0);
3525  float8 bound1 = PG_GETARG_FLOAT8(1);
3526  float8 bound2 = PG_GETARG_FLOAT8(2);
3527  int32 count = PG_GETARG_INT32(3);
3528  int32 result;
3529 
3530  if (count <= 0.0)
3531  ereport(ERROR,
3532  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3533  errmsg("count must be greater than zero")));
3534 
3535  if (isnan(operand) || isnan(bound1) || isnan(bound2))
3536  ereport(ERROR,
3537  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3538  errmsg("operand, lower bound, and upper bound cannot be NaN")));
3539 
3540  /* Note that we allow "operand" to be infinite */
3541  if (isinf(bound1) || isinf(bound2))
3542  ereport(ERROR,
3543  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3544  errmsg("lower and upper bounds must be finite")));
3545 
3546  if (bound1 < bound2)
3547  {
3548  if (operand < bound1)
3549  result = 0;
3550  else if (operand >= bound2)
3551  {
3552  if (pg_add_s32_overflow(count, 1, &result))
3553  ereport(ERROR,
3554  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3555  errmsg("integer out of range")));
3556  }
3557  else
3558  result = ((float8) count * (operand - bound1) / (bound2 - bound1)) + 1;
3559  }
3560  else if (bound1 > bound2)
3561  {
3562  if (operand > bound1)
3563  result = 0;
3564  else if (operand <= bound2)
3565  {
3566  if (pg_add_s32_overflow(count, 1, &result))
3567  ereport(ERROR,
3568  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3569  errmsg("integer out of range")));
3570  }
3571  else
3572  result = ((float8) count * (bound1 - operand) / (bound1 - bound2)) + 1;
3573  }
3574  else
3575  {
3576  ereport(ERROR,
3577  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3578  errmsg("lower bound cannot equal upper bound")));
3579  result = 0; /* keep the compiler quiet */
3580  }
3581 
3582  PG_RETURN_INT32(result);
3583 }
3584 
3585 /* ========== PRIVATE ROUTINES ========== */
3586 
3587 #ifndef HAVE_CBRT
3588 
3589 static double
3590 cbrt(double x)
3591 {
3592  int isneg = (x < 0.0);
3593  double absx = fabs(x);
3594  double tmpres = pow(absx, (double) 1.0 / (double) 3.0);
3595 
3596  /*
3597  * The result is somewhat inaccurate --- not really pow()'s fault, as the
3598  * exponent it's handed contains roundoff error. We can improve the
3599  * accuracy by doing one iteration of Newton's formula. Beware of zero
3600  * input however.
3601  */
3602  if (tmpres > 0.0)
3603  tmpres -= (tmpres - absx / (tmpres * tmpres)) / (double) 3.0;
3604 
3605  return isneg ? -tmpres : tmpres;
3606 }
3607 
3608 #endif /* !HAVE_CBRT */
Datum float48lt(PG_FUNCTION_ARGS)
Definition: float.c:3415
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
Datum float8ne(PG_FUNCTION_ARGS)
Definition: float.c:1092
Datum dtoi2(PG_FUNCTION_ARGS)
Definition: float.c:1240
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:246
double get_float8_nan(void)
Definition: float.c:167
signed short int16
Definition: c.h:283
Datum dlog1(PG_FUNCTION_ARGS)
Definition: float.c:1531
Datum float4pl(PG_FUNCTION_ARGS)
Definition: float.c:802
Datum float4mi(PG_FUNCTION_ARGS)
Definition: float.c:822
Datum float84ge(PG_FUNCTION_ARGS)
Definition: float.c:3499
Datum dcos(PG_FUNCTION_ARGS)
Definition: float.c:1700
float8 degree_c_sixty
Definition: float.c:89
Datum dacos(PG_FUNCTION_ARGS)
Definition: float.c:1590
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define cbrt
Definition: float.c:107
Datum radians(PG_FUNCTION_ARGS)
Definition: float.c:2401
Datum float8_stddev_pop(PG_FUNCTION_ARGS)
Definition: float.c:2713
static float8 cot_45
Definition: float.c:79
Datum float4eq(PG_FUNCTION_ARGS)
Definition: float.c:969
Datum float8larger(PG_FUNCTION_ARGS)
Definition: float.c:761
float8 degree_c_one
Definition: float.c:91
#define PG_RETURN_FLOAT4(x)
Definition: fmgr.h:325
Datum dcosd(PG_FUNCTION_ARGS)
Definition: float.c:2138
Datum float8_regr_syy(PG_FUNCTION_ARGS)
Definition: float.c:2950
Datum float4le(PG_FUNCTION_ARGS)
Definition: float.c:996
Datum datand(PG_FUNCTION_ARGS)
Definition: float.c:2006
Datum float48mi(PG_FUNCTION_ARGS)
Definition: float.c:3282
#define INIT_DEGREE_CONSTANTS()
Definition: float.c:1859
float8 degree_c_one_half
Definition: float.c:90
Datum float4larger(PG_FUNCTION_ARGS)
Definition: float.c:694
Datum float8mi(PG_FUNCTION_ARGS)
Definition: float.c:884
Datum float8_regr_sxy(PG_FUNCTION_ARGS)
Definition: float.c:2979
Datum dsin(PG_FUNCTION_ARGS)
Definition: float.c:1767
Datum float8gt(PG_FUNCTION_ARGS)
Definition: float.c:1119
Datum dpi(PG_FUNCTION_ARGS)
Definition: float.c:2391
Datum float48eq(PG_FUNCTION_ARGS)
Definition: float.c:3397
Datum btfloat8cmp(PG_FUNCTION_ARGS)
Definition: float.c:1137
char * float8out_internal(double num)
Definition: float.c:597
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:419
static double asind_q1(double x)
Definition: float.c:1876
Datum float8_var_samp(PG_FUNCTION_ARGS)
Definition: float.c:2684
static bool degree_consts_set
Definition: float.c:72
long random(void)
Definition: random.c:22
Datum i4tof(PG_FUNCTION_ARGS)
Definition: float.c:1315
Datum float4ge(PG_FUNCTION_ARGS)
Definition: float.c:1014
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
Datum float8um(PG_FUNCTION_ARGS)
Definition: float.c:743
char * pstrdup(const char *in)
Definition: mcxt.c:1076
Datum ftod(PG_FUNCTION_ARGS)
Definition: float.c:1194
void pq_sendfloat8(StringInfo buf, float8 f)
Definition: pqformat.c:278
StringInfoData * StringInfo
Definition: stringinfo.h:43
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
Datum dpow(PG_FUNCTION_ARGS)
Definition: float.c:1459
#define MAXDOUBLEWIDTH
Definition: float.c:49
Datum float84div(PG_FUNCTION_ARGS)
Definition: float.c:3370
float get_float4_nan(void)
Definition: float.c:180
static double sind_q1(double x)
Definition: float.c:2099
Datum float8up(PG_FUNCTION_ARGS)
Definition: float.c:753
Datum dtrunc(PG_FUNCTION_ARGS)
Definition: float.c:1405
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
Datum float8_covar_pop(PG_FUNCTION_ARGS)
Definition: float.c:3047
Datum float48le(PG_FUNCTION_ARGS)
Definition: float.c:3424
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Datum ascii(PG_FUNCTION_ARGS)
Datum dceil(PG_FUNCTION_ARGS)
Definition: float.c:1357
Datum float8eq(PG_FUNCTION_ARGS)
Definition: float.c:1083
#define PG_RETURN_INT16(x)
Definition: fmgr.h:316
void pq_sendfloat4(StringInfo buf, float4 f)
Definition: pqformat.c:254
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum btfloat4cmp(PG_FUNCTION_ARGS)
Definition: float.c:1023
Datum dround(PG_FUNCTION_ARGS)
Definition: float.c:1345
static float8 acos_0_5
Definition: float.c:76
Datum float8_regr_r2(PG_FUNCTION_ARGS)
Definition: float.c:3143
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum float84ne(PG_FUNCTION_ARGS)
Definition: float.c:3463
float8 degree_c_thirty
Definition: float.c:87
static void init_degree_constants(void)
Definition: float.c:1847
Datum float8ge(PG_FUNCTION_ARGS)
Definition: float.c:1128
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:330
Datum float8_regr_sxx(PG_FUNCTION_ARGS)
Definition: float.c:2921
Datum drandom(PG_FUNCTION_ARGS)
Definition: float.c:2417
#define MAXFLOATWIDTH
Definition: float.c:48
Datum dlog10(PG_FUNCTION_ARGS)
Definition: float.c:1560
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
Datum float8_avg(PG_FUNCTION_ARGS)
Definition: float.c:2635
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:1053
int float4_cmp_internal(float4 a, float4 b)
Definition: float.c:939
signed int int32
Definition: c.h:284
Datum float48pl(PG_FUNCTION_ARGS)
Definition: float.c:3270
Datum float4_accum(PG_FUNCTION_ARGS)
Definition: float.c:2582
Datum float8send(PG_FUNCTION_ARGS)
Definition: float.c:641
float get_float4_infinity(void)
Definition: float.c:147
Datum float4up(PG_FUNCTION_ARGS)
Definition: float.c:686
Datum float48ge(PG_FUNCTION_ARGS)
Definition: float.c:3442
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
Datum float8_regr_slope(PG_FUNCTION_ARGS)
Definition: float.c:3187
Datum datan2(PG_FUNCTION_ARGS)
Definition: float.c:1675
Datum ftoi2(PG_FUNCTION_ARGS)
Definition: float.c:1298
Datum dtof(PG_FUNCTION_ARGS)
Definition: float.c:1206
Datum float8pl(PG_FUNCTION_ARGS)
Definition: float.c:871
double float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string)
Definition: float.c:445
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:429
Datum float84pl(PG_FUNCTION_ARGS)
Definition: float.c:3330
Datum float4div(PG_FUNCTION_ARGS)
Definition: float.c:847
#define ARR_DIMS(a)
Definition: array.h:279
static double acosd_q1(double x)
Definition: float.c:1909
Datum dcbrt(PG_FUNCTION_ARGS)
Definition: float.c:1444
Datum setseed(PG_FUNCTION_ARGS)
Definition: float.c:2432
static int btfloat8fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: float.c:1146
int isinf(double x)
Datum float8abs(PG_FUNCTION_ARGS)
Definition: float.c:731
char sign
Definition: informix.c:693
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:107
static float8 atan_1_0
Definition: float.c:77
Datum dasin(PG_FUNCTION_ARGS)
Definition: float.c:1620
#define RADIANS_PER_DEGREE
Definition: float.c:36
#define ARR_DATA_PTR(a)
Definition: array.h:307
Datum float8div(PG_FUNCTION_ARGS)
Definition: float.c:911
float8 degree_c_forty_five
Definition: float.c:88
#define M_PI
Definition: float.c:32
static char * buf
Definition: pg_test_fsync.c:67
Datum dtoi4(PG_FUNCTION_ARGS)
Definition: float.c:1220
Datum float8_regr_combine(PG_FUNCTION_ARGS)
Definition: float.c:2866
Datum float84mul(PG_FUNCTION_ARGS)
Definition: float.c:3356
#define MAX_RANDOM_VALUE
Datum datan(PG_FUNCTION_ARGS)
Definition: float.c:1650
static double cosd_0_to_60(double x)
Definition: float.c:2086
Datum float4abs(PG_FUNCTION_ARGS)
Definition: float.c:665
unsigned int uint32
Definition: c.h:296
#define ARR_HASNULL(a)
Definition: array.h:276
static float8 sin_30
Definition: float.c:73
double rint(double x)
Definition: rint.c:22
Datum ftoi4(PG_FUNCTION_ARGS)
Definition: float.c:1281
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:245
Datum dsind(PG_FUNCTION_ARGS)
Definition: float.c:2256
#define ereport(elevel, rest)
Definition: elog.h:122
Datum float8mul(PG_FUNCTION_ARGS)
Definition: float.c:897
Datum dfloor(PG_FUNCTION_ARGS)
Definition: float.c:1369
Datum btfloat48cmp(PG_FUNCTION_ARGS)
Definition: float.c:1164
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:220
Datum dsign(PG_FUNCTION_ARGS)
Definition: float.c:1382
Datum float4mul(PG_FUNCTION_ARGS)
Definition: float.c:834
double get_float8_infinity(void)
Definition: float.c:122
Datum float8_covar_samp(PG_FUNCTION_ARGS)
Definition: float.c:3075
Datum float8lt(PG_FUNCTION_ARGS)
Definition: float.c:1101
Datum float8_regr_intercept(PG_FUNCTION_ARGS)
Definition: float.c:3222
static float8 one_minus_cos_60
Definition: float.c:74
Datum float4recv(PG_FUNCTION_ARGS)
Definition: float.c:394
Datum degrees(PG_FUNCTION_ARGS)
Definition: float.c:2375
Datum float4out(PG_FUNCTION_ARGS)
Definition: float.c:360
Datum dcot(PG_FUNCTION_ARGS)
Definition: float.c:1740
float float4
Definition: c.h:428
Datum float48ne(PG_FUNCTION_ARGS)
Definition: float.c:3406
Datum float8recv(PG_FUNCTION_ARGS)
Definition: float.c:630
Datum float8_regr_avgx(PG_FUNCTION_ARGS)
Definition: float.c:3009
static double cosd_q1(double x)
Definition: float.c:2119
static double sind_0_to_30(double x)
Definition: float.c:2072
static float8 asin_0_5
Definition: float.c:75
Datum float8_accum(PG_FUNCTION_ARGS)
Definition: float.c:2531
#define DatumGetFloat8(X)
Definition: postgres.h:734
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
Datum float4ne(PG_FUNCTION_ARGS)
Definition: float.c:978
Datum float4smaller(PG_FUNCTION_ARGS)
Definition: float.c:708
Datum dexp(PG_FUNCTION_ARGS)
Definition: float.c:1512
Datum float84lt(PG_FUNCTION_ARGS)
Definition: float.c:3472
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
Datum dtand(PG_FUNCTION_ARGS)
Definition: float.c:2310
Datum float84mi(PG_FUNCTION_ARGS)
Definition: float.c:3343
Datum width_bucket_float8(PG_FUNCTION_ARGS)
Definition: float.c:3522
int extra_float_digits
Definition: float.c:69
Datum float8_var_pop(PG_FUNCTION_ARGS)
Definition: float.c:2655
Datum float8_regr_accum(PG_FUNCTION_ARGS)
Definition: float.c:2787
#define PG_RETURN_VOID()
Definition: fmgr.h:309
#define Float8GetDatumFast(X)
Definition: postgres.h:782
Datum btfloat8sortsupport(PG_FUNCTION_ARGS)
Definition: float.c:1155
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:490
#define DatumGetFloat4(X)
Definition: postgres.h:686
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:89
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
Datum float8smaller(PG_FUNCTION_ARGS)
Definition: float.c:775
Datum float4lt(PG_FUNCTION_ARGS)
Definition: float.c:987
#define newval
#define FLOAT8OID
Definition: pg_type.h:419
#define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid)
Definition: float.c:54
Datum float84gt(PG_FUNCTION_ARGS)
Definition: float.c:3490
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4127
float4 pq_getmsgfloat4(StringInfo msg)
Definition: pqformat.c:471
Datum i2tof(PG_FUNCTION_ARGS)
Definition: float.c:1327
Datum float48mul(PG_FUNCTION_ARGS)
Definition: float.c:3294
#define ARR_NDIM(a)
Definition: array.h:275
Datum dasind(PG_FUNCTION_ARGS)
Definition: float.c:1971
int is_infinite(double val)
Definition: float.c:200
Datum float8_corr(PG_FUNCTION_ARGS)
Definition: float.c:3103
Datum dsqrt(PG_FUNCTION_ARGS)
Definition: float.c:1423
Datum datan2d(PG_FUNCTION_ARGS)
Definition: float.c:2036
Datum i4tod(PG_FUNCTION_ARGS)
Definition: float.c:1257
Datum float8_combine(PG_FUNCTION_ARGS)
Definition: float.c:2495
static float8 * check_float8_array(ArrayType *transarray, const char *caller, int n)
Definition: float.c:2471
Datum float4gt(PG_FUNCTION_ARGS)
Definition: float.c:1005
Datum btfloat84cmp(PG_FUNCTION_ARGS)
Definition: float.c:1174
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum float8_stddev_samp(PG_FUNCTION_ARGS)
Definition: float.c:2742
static int btfloat4fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: float.c:1032
Datum float4send(PG_FUNCTION_ARGS)
Definition: float.c:405
Datum float84le(PG_FUNCTION_ARGS)
Definition: float.c:3481
void srandom(unsigned int seed)
Definition: srandom.c:22
void * arg
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
Datum float8out(PG_FUNCTION_ARGS)
Definition: float.c:582
Datum float48div(PG_FUNCTION_ARGS)
Definition: float.c:3307
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
Datum dcotd(PG_FUNCTION_ARGS)
Definition: float.c:2191
static float8 tan_45
Definition: float.c:78
#define elog
Definition: elog.h:219
Datum float8le(PG_FUNCTION_ARGS)
Definition: float.c:1110
Datum float8_regr_avgy(PG_FUNCTION_ARGS)
Definition: float.c:3028
Datum float84eq(PG_FUNCTION_ARGS)
Definition: float.c:3454
Datum dacosd(PG_FUNCTION_ARGS)
Definition: float.c:1936
#define ARR_ELEMTYPE(a)
Definition: array.h:277
Datum float48gt(PG_FUNCTION_ARGS)
Definition: float.c:3433
long val
Definition: informix.c:689
Datum float4um(PG_FUNCTION_ARGS)
Definition: float.c:676
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum i2tod(PG_FUNCTION_ARGS)
Definition: float.c:1269
Datum dtan(PG_FUNCTION_ARGS)
Definition: float.c:1793
Datum btfloat4sortsupport(PG_FUNCTION_ARGS)
Definition: float.c:1041