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