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