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_OR_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 {
1258  float4 base = PG_GETARG_FLOAT4(1);
1259  float8 offset = PG_GETARG_FLOAT8(2);
1260  bool sub = PG_GETARG_BOOL(3);
1261  bool less = PG_GETARG_BOOL(4);
1262  float8 sum;
1263 
1264  /*
1265  * Reject negative or NaN offset. Negative is per spec, and NaN is
1266  * because appropriate semantics for that seem non-obvious.
1267  */
1268  if (isnan(offset) || offset < 0)
1269  ereport(ERROR,
1270  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
1271  errmsg("invalid preceding or following size in window function")));
1272 
1273  /*
1274  * Deal with cases where val and/or base is NaN, following the rule that
1275  * NaN sorts after non-NaN (cf float8_cmp_internal). The offset cannot
1276  * affect the conclusion.
1277  */
1278  if (isnan(val))
1279  {
1280  if (isnan(base))
1281  PG_RETURN_BOOL(true); /* NAN = NAN */
1282  else
1283  PG_RETURN_BOOL(!less); /* NAN > non-NAN */
1284  }
1285  else if (isnan(base))
1286  {
1287  PG_RETURN_BOOL(less); /* non-NAN < NAN */
1288  }
1289 
1290  /*
1291  * Deal with infinite offset (necessarily +inf, at this point). We must
1292  * special-case this because if base happens to be -inf, their sum would
1293  * be NaN, which is an overflow-ish condition we should avoid.
1294  */
1295  if (isinf(offset))
1296  {
1297  PG_RETURN_BOOL(sub ? !less : less);
1298  }
1299 
1300  /*
1301  * Otherwise it should be safe to compute base +/- offset. We trust the
1302  * FPU to cope if base is +/-inf or the true sum would overflow, and
1303  * produce a suitably signed infinity, which will compare properly against
1304  * val whether or not that's infinity.
1305  */
1306  if (sub)
1307  sum = base - offset;
1308  else
1309  sum = base + offset;
1310 
1311  if (less)
1312  PG_RETURN_BOOL(val <= sum);
1313  else
1314  PG_RETURN_BOOL(val >= sum);
1315 }
1316 
1317 
1318 /*
1319  * ===================
1320  * CONVERSION ROUTINES
1321  * ===================
1322  */
1323 
1324 /*
1325  * ftod - converts a float4 number to a float8 number
1326  */
1327 Datum
1329 {
1330  float4 num = PG_GETARG_FLOAT4(0);
1331 
1332  PG_RETURN_FLOAT8((float8) num);
1333 }
1334 
1335 
1336 /*
1337  * dtof - converts a float8 number to a float4 number
1338  */
1339 Datum
1341 {
1342  float8 num = PG_GETARG_FLOAT8(0);
1343 
1344  CHECKFLOATVAL((float4) num, isinf(num), num == 0);
1345 
1346  PG_RETURN_FLOAT4((float4) num);
1347 }
1348 
1349 
1350 /*
1351  * dtoi4 - converts a float8 number to an int4 number
1352  */
1353 Datum
1355 {
1356  float8 num = PG_GETARG_FLOAT8(0);
1357  int32 result;
1358 
1359  /* 'Inf' is handled by INT_MAX */
1360  if (num < INT_MIN || num > INT_MAX || isnan(num))
1361  ereport(ERROR,
1362  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1363  errmsg("integer out of range")));
1364 
1365  result = (int32) rint(num);
1366  PG_RETURN_INT32(result);
1367 }
1368 
1369 
1370 /*
1371  * dtoi2 - converts a float8 number to an int2 number
1372  */
1373 Datum
1375 {
1376  float8 num = PG_GETARG_FLOAT8(0);
1377 
1378  if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
1379  ereport(ERROR,
1380  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1381  errmsg("smallint out of range")));
1382 
1383  PG_RETURN_INT16((int16) rint(num));
1384 }
1385 
1386 
1387 /*
1388  * i4tod - converts an int4 number to a float8 number
1389  */
1390 Datum
1392 {
1393  int32 num = PG_GETARG_INT32(0);
1394 
1395  PG_RETURN_FLOAT8((float8) num);
1396 }
1397 
1398 
1399 /*
1400  * i2tod - converts an int2 number to a float8 number
1401  */
1402 Datum
1404 {
1405  int16 num = PG_GETARG_INT16(0);
1406 
1407  PG_RETURN_FLOAT8((float8) num);
1408 }
1409 
1410 
1411 /*
1412  * ftoi4 - converts a float4 number to an int4 number
1413  */
1414 Datum
1416 {
1417  float4 num = PG_GETARG_FLOAT4(0);
1418 
1419  if (num < INT_MIN || num > INT_MAX || isnan(num))
1420  ereport(ERROR,
1421  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1422  errmsg("integer out of range")));
1423 
1424  PG_RETURN_INT32((int32) rint(num));
1425 }
1426 
1427 
1428 /*
1429  * ftoi2 - converts a float4 number to an int2 number
1430  */
1431 Datum
1433 {
1434  float4 num = PG_GETARG_FLOAT4(0);
1435 
1436  if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
1437  ereport(ERROR,
1438  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1439  errmsg("smallint out of range")));
1440 
1441  PG_RETURN_INT16((int16) rint(num));
1442 }
1443 
1444 
1445 /*
1446  * i4tof - converts an int4 number to a float4 number
1447  */
1448 Datum
1450 {
1451  int32 num = PG_GETARG_INT32(0);
1452 
1453  PG_RETURN_FLOAT4((float4) num);
1454 }
1455 
1456 
1457 /*
1458  * i2tof - converts an int2 number to a float4 number
1459  */
1460 Datum
1462 {
1463  int16 num = PG_GETARG_INT16(0);
1464 
1465  PG_RETURN_FLOAT4((float4) num);
1466 }
1467 
1468 
1469 /*
1470  * =======================
1471  * RANDOM FLOAT8 OPERATORS
1472  * =======================
1473  */
1474 
1475 /*
1476  * dround - returns ROUND(arg1)
1477  */
1478 Datum
1480 {
1481  float8 arg1 = PG_GETARG_FLOAT8(0);
1482 
1483  PG_RETURN_FLOAT8(rint(arg1));
1484 }
1485 
1486 /*
1487  * dceil - returns the smallest integer greater than or
1488  * equal to the specified float
1489  */
1490 Datum
1492 {
1493  float8 arg1 = PG_GETARG_FLOAT8(0);
1494 
1495  PG_RETURN_FLOAT8(ceil(arg1));
1496 }
1497 
1498 /*
1499  * dfloor - returns the largest integer lesser than or
1500  * equal to the specified float
1501  */
1502 Datum
1504 {
1505  float8 arg1 = PG_GETARG_FLOAT8(0);
1506 
1507  PG_RETURN_FLOAT8(floor(arg1));
1508 }
1509 
1510 /*
1511  * dsign - returns -1 if the argument is less than 0, 0
1512  * if the argument is equal to 0, and 1 if the
1513  * argument is greater than zero.
1514  */
1515 Datum
1517 {
1518  float8 arg1 = PG_GETARG_FLOAT8(0);
1519  float8 result;
1520 
1521  if (arg1 > 0)
1522  result = 1.0;
1523  else if (arg1 < 0)
1524  result = -1.0;
1525  else
1526  result = 0.0;
1527 
1528  PG_RETURN_FLOAT8(result);
1529 }
1530 
1531 /*
1532  * dtrunc - returns truncation-towards-zero of arg1,
1533  * arg1 >= 0 ... the greatest integer less
1534  * than or equal to arg1
1535  * arg1 < 0 ... the least integer greater
1536  * than or equal to arg1
1537  */
1538 Datum
1540 {
1541  float8 arg1 = PG_GETARG_FLOAT8(0);
1542  float8 result;
1543 
1544  if (arg1 >= 0)
1545  result = floor(arg1);
1546  else
1547  result = -floor(-arg1);
1548 
1549  PG_RETURN_FLOAT8(result);
1550 }
1551 
1552 
1553 /*
1554  * dsqrt - returns square root of arg1
1555  */
1556 Datum
1558 {
1559  float8 arg1 = PG_GETARG_FLOAT8(0);
1560  float8 result;
1561 
1562  if (arg1 < 0)
1563  ereport(ERROR,
1564  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1565  errmsg("cannot take square root of a negative number")));
1566 
1567  result = sqrt(arg1);
1568 
1569  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1570  PG_RETURN_FLOAT8(result);
1571 }
1572 
1573 
1574 /*
1575  * dcbrt - returns cube root of arg1
1576  */
1577 Datum
1579 {
1580  float8 arg1 = PG_GETARG_FLOAT8(0);
1581  float8 result;
1582 
1583  result = cbrt(arg1);
1584  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
1585  PG_RETURN_FLOAT8(result);
1586 }
1587 
1588 
1589 /*
1590  * dpow - returns pow(arg1,arg2)
1591  */
1592 Datum
1594 {
1595  float8 arg1 = PG_GETARG_FLOAT8(0);
1596  float8 arg2 = PG_GETARG_FLOAT8(1);
1597  float8 result;
1598 
1599  /*
1600  * The POSIX spec says that NaN ^ 0 = 1, and 1 ^ NaN = 1, while all other
1601  * cases with NaN inputs yield NaN (with no error). Many older platforms
1602  * get one or more of these cases wrong, so deal with them via explicit
1603  * logic rather than trusting pow(3).
1604  */
1605  if (isnan(arg1))
1606  {
1607  if (isnan(arg2) || arg2 != 0.0)
1609  PG_RETURN_FLOAT8(1.0);
1610  }
1611  if (isnan(arg2))
1612  {
1613  if (arg1 != 1.0)
1615  PG_RETURN_FLOAT8(1.0);
1616  }
1617 
1618  /*
1619  * The SQL spec requires that we emit a particular SQLSTATE error code for
1620  * certain error conditions. Specifically, we don't return a
1621  * divide-by-zero error code for 0 ^ -1.
1622  */
1623  if (arg1 == 0 && arg2 < 0)
1624  ereport(ERROR,
1625  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1626  errmsg("zero raised to a negative power is undefined")));
1627  if (arg1 < 0 && floor(arg2) != arg2)
1628  ereport(ERROR,
1629  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1630  errmsg("a negative number raised to a non-integer power yields a complex result")));
1631 
1632  /*
1633  * pow() sets errno only on some platforms, depending on whether it
1634  * follows _IEEE_, _POSIX_, _XOPEN_, or _SVID_, so we try to avoid using
1635  * errno. However, some platform/CPU combinations return errno == EDOM
1636  * and result == NaN for negative arg1 and very large arg2 (they must be
1637  * using something different from our floor() test to decide it's
1638  * invalid). Other platforms (HPPA) return errno == ERANGE and a large
1639  * (HUGE_VAL) but finite result to signal overflow.
1640  */
1641  errno = 0;
1642  result = pow(arg1, arg2);
1643  if (errno == EDOM && isnan(result))
1644  {
1645  if ((fabs(arg1) > 1 && arg2 >= 0) || (fabs(arg1) < 1 && arg2 < 0))
1646  /* The sign of Inf is not significant in this case. */
1647  result = get_float8_infinity();
1648  else if (fabs(arg1) != 1)
1649  result = 0;
1650  else
1651  result = 1;
1652  }
1653  else if (errno == ERANGE && result != 0 && !isinf(result))
1654  result = get_float8_infinity();
1655 
1656  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
1657  PG_RETURN_FLOAT8(result);
1658 }
1659 
1660 
1661 /*
1662  * dexp - returns the exponential function of arg1
1663  */
1664 Datum
1666 {
1667  float8 arg1 = PG_GETARG_FLOAT8(0);
1668  float8 result;
1669 
1670  errno = 0;
1671  result = exp(arg1);
1672  if (errno == ERANGE && result != 0 && !isinf(result))
1673  result = get_float8_infinity();
1674 
1675  CHECKFLOATVAL(result, isinf(arg1), false);
1676  PG_RETURN_FLOAT8(result);
1677 }
1678 
1679 
1680 /*
1681  * dlog1 - returns the natural logarithm of arg1
1682  */
1683 Datum
1685 {
1686  float8 arg1 = PG_GETARG_FLOAT8(0);
1687  float8 result;
1688 
1689  /*
1690  * Emit particular SQLSTATE error codes for ln(). This is required by the
1691  * SQL standard.
1692  */
1693  if (arg1 == 0.0)
1694  ereport(ERROR,
1695  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1696  errmsg("cannot take logarithm of zero")));
1697  if (arg1 < 0)
1698  ereport(ERROR,
1699  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1700  errmsg("cannot take logarithm of a negative number")));
1701 
1702  result = log(arg1);
1703 
1704  CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
1705  PG_RETURN_FLOAT8(result);
1706 }
1707 
1708 
1709 /*
1710  * dlog10 - returns the base 10 logarithm of arg1
1711  */
1712 Datum
1714 {
1715  float8 arg1 = PG_GETARG_FLOAT8(0);
1716  float8 result;
1717 
1718  /*
1719  * Emit particular SQLSTATE error codes for log(). The SQL spec doesn't
1720  * define log(), but it does define ln(), so it makes sense to emit the
1721  * same error code for an analogous error condition.
1722  */
1723  if (arg1 == 0.0)
1724  ereport(ERROR,
1725  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1726  errmsg("cannot take logarithm of zero")));
1727  if (arg1 < 0)
1728  ereport(ERROR,
1729  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1730  errmsg("cannot take logarithm of a negative number")));
1731 
1732  result = log10(arg1);
1733 
1734  CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
1735  PG_RETURN_FLOAT8(result);
1736 }
1737 
1738 
1739 /*
1740  * dacos - returns the arccos of arg1 (radians)
1741  */
1742 Datum
1744 {
1745  float8 arg1 = PG_GETARG_FLOAT8(0);
1746  float8 result;
1747 
1748  /* Per the POSIX spec, return NaN if the input is NaN */
1749  if (isnan(arg1))
1751 
1752  /*
1753  * The principal branch of the inverse cosine function maps values in the
1754  * range [-1, 1] to values in the range [0, Pi], so we should reject any
1755  * inputs outside that range and the result will always be finite.
1756  */
1757  if (arg1 < -1.0 || arg1 > 1.0)
1758  ereport(ERROR,
1759  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1760  errmsg("input is out of range")));
1761 
1762  result = acos(arg1);
1763 
1764  CHECKFLOATVAL(result, false, true);
1765  PG_RETURN_FLOAT8(result);
1766 }
1767 
1768 
1769 /*
1770  * dasin - returns the arcsin of arg1 (radians)
1771  */
1772 Datum
1774 {
1775  float8 arg1 = PG_GETARG_FLOAT8(0);
1776  float8 result;
1777 
1778  /* Per the POSIX spec, return NaN if the input is NaN */
1779  if (isnan(arg1))
1781 
1782  /*
1783  * The principal branch of the inverse sine function maps values in the
1784  * range [-1, 1] to values in the range [-Pi/2, Pi/2], so we should reject
1785  * any inputs outside that range and the result will always be finite.
1786  */
1787  if (arg1 < -1.0 || arg1 > 1.0)
1788  ereport(ERROR,
1789  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1790  errmsg("input is out of range")));
1791 
1792  result = asin(arg1);
1793 
1794  CHECKFLOATVAL(result, false, true);
1795  PG_RETURN_FLOAT8(result);
1796 }
1797 
1798 
1799 /*
1800  * datan - returns the arctan of arg1 (radians)
1801  */
1802 Datum
1804 {
1805  float8 arg1 = PG_GETARG_FLOAT8(0);
1806  float8 result;
1807 
1808  /* Per the POSIX spec, return NaN if the input is NaN */
1809  if (isnan(arg1))
1811 
1812  /*
1813  * The principal branch of the inverse tangent function maps all inputs to
1814  * values in the range [-Pi/2, Pi/2], so the result should always be
1815  * finite, even if the input is infinite.
1816  */
1817  result = atan(arg1);
1818 
1819  CHECKFLOATVAL(result, false, true);
1820  PG_RETURN_FLOAT8(result);
1821 }
1822 
1823 
1824 /*
1825  * atan2 - returns the arctan of arg1/arg2 (radians)
1826  */
1827 Datum
1829 {
1830  float8 arg1 = PG_GETARG_FLOAT8(0);
1831  float8 arg2 = PG_GETARG_FLOAT8(1);
1832  float8 result;
1833 
1834  /* Per the POSIX spec, return NaN if either input is NaN */
1835  if (isnan(arg1) || isnan(arg2))
1837 
1838  /*
1839  * atan2 maps all inputs to values in the range [-Pi, Pi], so the result
1840  * should always be finite, even if the inputs are infinite.
1841  */
1842  result = atan2(arg1, arg2);
1843 
1844  CHECKFLOATVAL(result, false, true);
1845  PG_RETURN_FLOAT8(result);
1846 }
1847 
1848 
1849 /*
1850  * dcos - returns the cosine 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  /*
1863  * cos() is periodic and so theoretically can work for all finite inputs,
1864  * but some implementations may choose to throw error if the input is so
1865  * large that there are no significant digits in the result. So we should
1866  * check for errors. POSIX allows an error to be reported either via
1867  * errno or via fetestexcept(), but currently we only support checking
1868  * errno. (fetestexcept() is rumored to report underflow unreasonably
1869  * early on some platforms, so it's not clear that believing it would be a
1870  * net improvement anyway.)
1871  *
1872  * For infinite inputs, POSIX specifies that the trigonometric functions
1873  * should return a domain error; but we won't notice that unless the
1874  * platform reports via errno, so also explicitly test for infinite
1875  * inputs.
1876  */
1877  errno = 0;
1878  result = cos(arg1);
1879  if (errno != 0 || isinf(arg1))
1880  ereport(ERROR,
1881  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1882  errmsg("input is out of range")));
1883 
1884  CHECKFLOATVAL(result, false, true);
1885  PG_RETURN_FLOAT8(result);
1886 }
1887 
1888 
1889 /*
1890  * dcot - returns the cotangent of arg1 (radians)
1891  */
1892 Datum
1894 {
1895  float8 arg1 = PG_GETARG_FLOAT8(0);
1896  float8 result;
1897 
1898  /* Per the POSIX spec, return NaN if the input is NaN */
1899  if (isnan(arg1))
1901 
1902  /* Be sure to throw an error if the input is infinite --- see dcos() */
1903  errno = 0;
1904  result = tan(arg1);
1905  if (errno != 0 || isinf(arg1))
1906  ereport(ERROR,
1907  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1908  errmsg("input is out of range")));
1909 
1910  result = 1.0 / result;
1911  CHECKFLOATVAL(result, true /* cot(0) == Inf */ , true);
1912  PG_RETURN_FLOAT8(result);
1913 }
1914 
1915 
1916 /*
1917  * dsin - returns the sine of arg1 (radians)
1918  */
1919 Datum
1921 {
1922  float8 arg1 = PG_GETARG_FLOAT8(0);
1923  float8 result;
1924 
1925  /* Per the POSIX spec, return NaN if the input is NaN */
1926  if (isnan(arg1))
1928 
1929  /* Be sure to throw an error if the input is infinite --- see dcos() */
1930  errno = 0;
1931  result = sin(arg1);
1932  if (errno != 0 || isinf(arg1))
1933  ereport(ERROR,
1934  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1935  errmsg("input is out of range")));
1936 
1937  CHECKFLOATVAL(result, false, true);
1938  PG_RETURN_FLOAT8(result);
1939 }
1940 
1941 
1942 /*
1943  * dtan - returns the tangent of arg1 (radians)
1944  */
1945 Datum
1947 {
1948  float8 arg1 = PG_GETARG_FLOAT8(0);
1949  float8 result;
1950 
1951  /* Per the POSIX spec, return NaN if the input is NaN */
1952  if (isnan(arg1))
1954 
1955  /* Be sure to throw an error if the input is infinite --- see dcos() */
1956  errno = 0;
1957  result = tan(arg1);
1958  if (errno != 0 || isinf(arg1))
1959  ereport(ERROR,
1960  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1961  errmsg("input is out of range")));
1962 
1963  CHECKFLOATVAL(result, true /* tan(pi/2) == Inf */ , true);
1964  PG_RETURN_FLOAT8(result);
1965 }
1966 
1967 
1968 /* ========== DEGREE-BASED TRIGONOMETRIC FUNCTIONS ========== */
1969 
1970 
1971 /*
1972  * Initialize the cached constants declared at the head of this file
1973  * (sin_30 etc). The fact that we need those at all, let alone need this
1974  * Rube-Goldberg-worthy method of initializing them, is because there are
1975  * compilers out there that will precompute expressions such as sin(constant)
1976  * using a sin() function different from what will be used at runtime. If we
1977  * want exact results, we must ensure that none of the scaling constants used
1978  * in the degree-based trig functions are computed that way. To do so, we
1979  * compute them from the variables degree_c_thirty etc, which are also really
1980  * constants, but the compiler cannot assume that.
1981  *
1982  * Other hazards we are trying to forestall with this kluge include the
1983  * possibility that compilers will rearrange the expressions, or compute
1984  * some intermediate results in registers wider than a standard double.
1985  *
1986  * In the places where we use these constants, the typical pattern is like
1987  * volatile float8 sin_x = sin(x * RADIANS_PER_DEGREE);
1988  * return (sin_x / sin_30);
1989  * where we hope to get a value of exactly 1.0 from the division when x = 30.
1990  * The volatile temporary variable is needed on machines with wide float
1991  * registers, to ensure that the result of sin(x) is rounded to double width
1992  * the same as the value of sin_30 has been. Experimentation with gcc shows
1993  * that marking the temp variable volatile is necessary to make the store and
1994  * reload actually happen; hopefully the same trick works for other compilers.
1995  * (gcc's documentation suggests using the -ffloat-store compiler switch to
1996  * ensure this, but that is compiler-specific and it also pessimizes code in
1997  * many places where we don't care about this.)
1998  */
1999 static void
2001 {
2003  one_minus_cos_60 = 1.0 - cos(degree_c_sixty * RADIANS_PER_DEGREE);
2004  asin_0_5 = asin(degree_c_one_half);
2005  acos_0_5 = acos(degree_c_one_half);
2006  atan_1_0 = atan(degree_c_one);
2009  degree_consts_set = true;
2010 }
2011 
2012 #define INIT_DEGREE_CONSTANTS() \
2013 do { \
2014  if (!degree_consts_set) \
2015  init_degree_constants(); \
2016 } while(0)
2017 
2018 
2019 /*
2020  * asind_q1 - returns the inverse sine of x in degrees, for x in
2021  * the range [0, 1]. The result is an angle in the
2022  * first quadrant --- [0, 90] degrees.
2023  *
2024  * For the 3 special case inputs (0, 0.5 and 1), this
2025  * function will return exact values (0, 30 and 90
2026  * degrees respectively).
2027  */
2028 static double
2029 asind_q1(double x)
2030 {
2031  /*
2032  * Stitch together inverse sine and cosine functions for the ranges [0,
2033  * 0.5] and (0.5, 1]. Each expression below is guaranteed to return
2034  * exactly 30 for x=0.5, so the result is a continuous monotonic function
2035  * over the full range.
2036  */
2037  if (x <= 0.5)
2038  {
2039  volatile float8 asin_x = asin(x);
2040 
2041  return (asin_x / asin_0_5) * 30.0;
2042  }
2043  else
2044  {
2045  volatile float8 acos_x = acos(x);
2046 
2047  return 90.0 - (acos_x / acos_0_5) * 60.0;
2048  }
2049 }
2050 
2051 
2052 /*
2053  * acosd_q1 - returns the inverse cosine of x in degrees, for x in
2054  * the range [0, 1]. The result is an angle in the
2055  * first quadrant --- [0, 90] degrees.
2056  *
2057  * For the 3 special case inputs (0, 0.5 and 1), this
2058  * function will return exact values (0, 60 and 90
2059  * degrees respectively).
2060  */
2061 static double
2062 acosd_q1(double x)
2063 {
2064  /*
2065  * Stitch together inverse sine and cosine functions for the ranges [0,
2066  * 0.5] and (0.5, 1]. Each expression below is guaranteed to return
2067  * exactly 60 for x=0.5, so the result is a continuous monotonic function
2068  * over the full range.
2069  */
2070  if (x <= 0.5)
2071  {
2072  volatile float8 asin_x = asin(x);
2073 
2074  return 90.0 - (asin_x / asin_0_5) * 30.0;
2075  }
2076  else
2077  {
2078  volatile float8 acos_x = acos(x);
2079 
2080  return (acos_x / acos_0_5) * 60.0;
2081  }
2082 }
2083 
2084 
2085 /*
2086  * dacosd - returns the arccos of arg1 (degrees)
2087  */
2088 Datum
2090 {
2091  float8 arg1 = PG_GETARG_FLOAT8(0);
2092  float8 result;
2093 
2094  /* Per the POSIX spec, return NaN if the input is NaN */
2095  if (isnan(arg1))
2097 
2099 
2100  /*
2101  * The principal branch of the inverse cosine function maps values in the
2102  * range [-1, 1] to values in the range [0, 180], so we should reject any
2103  * inputs outside that range and the result will always be finite.
2104  */
2105  if (arg1 < -1.0 || arg1 > 1.0)
2106  ereport(ERROR,
2107  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2108  errmsg("input is out of range")));
2109 
2110  if (arg1 >= 0.0)
2111  result = acosd_q1(arg1);
2112  else
2113  result = 90.0 + asind_q1(-arg1);
2114 
2115  CHECKFLOATVAL(result, false, true);
2116  PG_RETURN_FLOAT8(result);
2117 }
2118 
2119 
2120 /*
2121  * dasind - returns the arcsin of arg1 (degrees)
2122  */
2123 Datum
2125 {
2126  float8 arg1 = PG_GETARG_FLOAT8(0);
2127  float8 result;
2128 
2129  /* Per the POSIX spec, return NaN if the input is NaN */
2130  if (isnan(arg1))
2132 
2134 
2135  /*
2136  * The principal branch of the inverse sine function maps values in the
2137  * range [-1, 1] to values in the range [-90, 90], so we should reject any
2138  * inputs outside that range and the result will always be finite.
2139  */
2140  if (arg1 < -1.0 || arg1 > 1.0)
2141  ereport(ERROR,
2142  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2143  errmsg("input is out of range")));
2144 
2145  if (arg1 >= 0.0)
2146  result = asind_q1(arg1);
2147  else
2148  result = -asind_q1(-arg1);
2149 
2150  CHECKFLOATVAL(result, false, true);
2151  PG_RETURN_FLOAT8(result);
2152 }
2153 
2154 
2155 /*
2156  * datand - returns the arctan of arg1 (degrees)
2157  */
2158 Datum
2160 {
2161  float8 arg1 = PG_GETARG_FLOAT8(0);
2162  float8 result;
2163  volatile float8 atan_arg1;
2164 
2165  /* Per the POSIX spec, return NaN if the input is NaN */
2166  if (isnan(arg1))
2168 
2170 
2171  /*
2172  * The principal branch of the inverse tangent function maps all inputs to
2173  * values in the range [-90, 90], so the result should always be finite,
2174  * even if the input is infinite. Additionally, we take care to ensure
2175  * than when arg1 is 1, the result is exactly 45.
2176  */
2177  atan_arg1 = atan(arg1);
2178  result = (atan_arg1 / atan_1_0) * 45.0;
2179 
2180  CHECKFLOATVAL(result, false, true);
2181  PG_RETURN_FLOAT8(result);
2182 }
2183 
2184 
2185 /*
2186  * atan2d - returns the arctan of arg1/arg2 (degrees)
2187  */
2188 Datum
2190 {
2191  float8 arg1 = PG_GETARG_FLOAT8(0);
2192  float8 arg2 = PG_GETARG_FLOAT8(1);
2193  float8 result;
2194  volatile float8 atan2_arg1_arg2;
2195 
2196  /* Per the POSIX spec, return NaN if either input is NaN */
2197  if (isnan(arg1) || isnan(arg2))
2199 
2201 
2202  /*
2203  * atan2d maps all inputs to values in the range [-180, 180], so the
2204  * result should always be finite, even if the inputs are infinite.
2205  *
2206  * Note: this coding assumes that atan(1.0) is a suitable scaling constant
2207  * to get an exact result from atan2(). This might well fail on us at
2208  * some point, requiring us to decide exactly what inputs we think we're
2209  * going to guarantee an exact result for.
2210  */
2211  atan2_arg1_arg2 = atan2(arg1, arg2);
2212  result = (atan2_arg1_arg2 / atan_1_0) * 45.0;
2213 
2214  CHECKFLOATVAL(result, false, true);
2215  PG_RETURN_FLOAT8(result);
2216 }
2217 
2218 
2219 /*
2220  * sind_0_to_30 - returns the sine of an angle that lies between 0 and
2221  * 30 degrees. This will return exactly 0 when x is 0,
2222  * and exactly 0.5 when x is 30 degrees.
2223  */
2224 static double
2225 sind_0_to_30(double x)
2226 {
2227  volatile float8 sin_x = sin(x * RADIANS_PER_DEGREE);
2228 
2229  return (sin_x / sin_30) / 2.0;
2230 }
2231 
2232 
2233 /*
2234  * cosd_0_to_60 - returns the cosine of an angle that lies between 0
2235  * and 60 degrees. This will return exactly 1 when x
2236  * is 0, and exactly 0.5 when x is 60 degrees.
2237  */
2238 static double
2239 cosd_0_to_60(double x)
2240 {
2241  volatile float8 one_minus_cos_x = 1.0 - cos(x * RADIANS_PER_DEGREE);
2242 
2243  return 1.0 - (one_minus_cos_x / one_minus_cos_60) / 2.0;
2244 }
2245 
2246 
2247 /*
2248  * sind_q1 - returns the sine of an angle in the first quadrant
2249  * (0 to 90 degrees).
2250  */
2251 static double
2252 sind_q1(double x)
2253 {
2254  /*
2255  * Stitch together the sine and cosine functions for the ranges [0, 30]
2256  * and (30, 90]. These guarantee to return exact answers at their
2257  * endpoints, so the overall result is a continuous monotonic function
2258  * that gives exact results when x = 0, 30 and 90 degrees.
2259  */
2260  if (x <= 30.0)
2261  return sind_0_to_30(x);
2262  else
2263  return cosd_0_to_60(90.0 - x);
2264 }
2265 
2266 
2267 /*
2268  * cosd_q1 - returns the cosine of an angle in the first quadrant
2269  * (0 to 90 degrees).
2270  */
2271 static double
2272 cosd_q1(double x)
2273 {
2274  /*
2275  * Stitch together the sine and cosine functions for the ranges [0, 60]
2276  * and (60, 90]. These guarantee to return exact answers at their
2277  * endpoints, so the overall result is a continuous monotonic function
2278  * that gives exact results when x = 0, 60 and 90 degrees.
2279  */
2280  if (x <= 60.0)
2281  return cosd_0_to_60(x);
2282  else
2283  return sind_0_to_30(90.0 - x);
2284 }
2285 
2286 
2287 /*
2288  * dcosd - returns the cosine of arg1 (degrees)
2289  */
2290 Datum
2292 {
2293  float8 arg1 = PG_GETARG_FLOAT8(0);
2294  float8 result;
2295  int sign = 1;
2296 
2297  /*
2298  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2299  * if the input is infinite.
2300  */
2301  if (isnan(arg1))
2303 
2304  if (isinf(arg1))
2305  ereport(ERROR,
2306  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2307  errmsg("input is out of range")));
2308 
2310 
2311  /* Reduce the range of the input to [0,90] degrees */
2312  arg1 = fmod(arg1, 360.0);
2313 
2314  if (arg1 < 0.0)
2315  {
2316  /* cosd(-x) = cosd(x) */
2317  arg1 = -arg1;
2318  }
2319 
2320  if (arg1 > 180.0)
2321  {
2322  /* cosd(360-x) = cosd(x) */
2323  arg1 = 360.0 - arg1;
2324  }
2325 
2326  if (arg1 > 90.0)
2327  {
2328  /* cosd(180-x) = -cosd(x) */
2329  arg1 = 180.0 - arg1;
2330  sign = -sign;
2331  }
2332 
2333  result = sign * cosd_q1(arg1);
2334 
2335  CHECKFLOATVAL(result, false, true);
2336  PG_RETURN_FLOAT8(result);
2337 }
2338 
2339 
2340 /*
2341  * dcotd - returns the cotangent of arg1 (degrees)
2342  */
2343 Datum
2345 {
2346  float8 arg1 = PG_GETARG_FLOAT8(0);
2347  float8 result;
2348  volatile float8 cot_arg1;
2349  int sign = 1;
2350 
2351  /*
2352  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2353  * if the input is infinite.
2354  */
2355  if (isnan(arg1))
2357 
2358  if (isinf(arg1))
2359  ereport(ERROR,
2360  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2361  errmsg("input is out of range")));
2362 
2364 
2365  /* Reduce the range of the input to [0,90] degrees */
2366  arg1 = fmod(arg1, 360.0);
2367 
2368  if (arg1 < 0.0)
2369  {
2370  /* cotd(-x) = -cotd(x) */
2371  arg1 = -arg1;
2372  sign = -sign;
2373  }
2374 
2375  if (arg1 > 180.0)
2376  {
2377  /* cotd(360-x) = -cotd(x) */
2378  arg1 = 360.0 - arg1;
2379  sign = -sign;
2380  }
2381 
2382  if (arg1 > 90.0)
2383  {
2384  /* cotd(180-x) = -cotd(x) */
2385  arg1 = 180.0 - arg1;
2386  sign = -sign;
2387  }
2388 
2389  cot_arg1 = cosd_q1(arg1) / sind_q1(arg1);
2390  result = sign * (cot_arg1 / cot_45);
2391 
2392  /*
2393  * On some machines we get cotd(270) = minus zero, but this isn't always
2394  * true. For portability, and because the user constituency for this
2395  * function probably doesn't want minus zero, force it to plain zero.
2396  */
2397  if (result == 0.0)
2398  result = 0.0;
2399 
2400  CHECKFLOATVAL(result, true /* cotd(0) == Inf */ , true);
2401  PG_RETURN_FLOAT8(result);
2402 }
2403 
2404 
2405 /*
2406  * dsind - returns the sine of arg1 (degrees)
2407  */
2408 Datum
2410 {
2411  float8 arg1 = PG_GETARG_FLOAT8(0);
2412  float8 result;
2413  int sign = 1;
2414 
2415  /*
2416  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2417  * if the input is infinite.
2418  */
2419  if (isnan(arg1))
2421 
2422  if (isinf(arg1))
2423  ereport(ERROR,
2424  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2425  errmsg("input is out of range")));
2426 
2428 
2429  /* Reduce the range of the input to [0,90] degrees */
2430  arg1 = fmod(arg1, 360.0);
2431 
2432  if (arg1 < 0.0)
2433  {
2434  /* sind(-x) = -sind(x) */
2435  arg1 = -arg1;
2436  sign = -sign;
2437  }
2438 
2439  if (arg1 > 180.0)
2440  {
2441  /* sind(360-x) = -sind(x) */
2442  arg1 = 360.0 - arg1;
2443  sign = -sign;
2444  }
2445 
2446  if (arg1 > 90.0)
2447  {
2448  /* sind(180-x) = sind(x) */
2449  arg1 = 180.0 - arg1;
2450  }
2451 
2452  result = sign * sind_q1(arg1);
2453 
2454  CHECKFLOATVAL(result, false, true);
2455  PG_RETURN_FLOAT8(result);
2456 }
2457 
2458 
2459 /*
2460  * dtand - returns the tangent of arg1 (degrees)
2461  */
2462 Datum
2464 {
2465  float8 arg1 = PG_GETARG_FLOAT8(0);
2466  float8 result;
2467  volatile float8 tan_arg1;
2468  int sign = 1;
2469 
2470  /*
2471  * Per the POSIX spec, return NaN if the input is NaN and throw an error
2472  * if the input is infinite.
2473  */
2474  if (isnan(arg1))
2476 
2477  if (isinf(arg1))
2478  ereport(ERROR,
2479  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2480  errmsg("input is out of range")));
2481 
2483 
2484  /* Reduce the range of the input to [0,90] degrees */
2485  arg1 = fmod(arg1, 360.0);
2486 
2487  if (arg1 < 0.0)
2488  {
2489  /* tand(-x) = -tand(x) */
2490  arg1 = -arg1;
2491  sign = -sign;
2492  }
2493 
2494  if (arg1 > 180.0)
2495  {
2496  /* tand(360-x) = -tand(x) */
2497  arg1 = 360.0 - arg1;
2498  sign = -sign;
2499  }
2500 
2501  if (arg1 > 90.0)
2502  {
2503  /* tand(180-x) = -tand(x) */
2504  arg1 = 180.0 - arg1;
2505  sign = -sign;
2506  }
2507 
2508  tan_arg1 = sind_q1(arg1) / cosd_q1(arg1);
2509  result = sign * (tan_arg1 / tan_45);
2510 
2511  /*
2512  * On some machines we get tand(180) = minus zero, but this isn't always
2513  * true. For portability, and because the user constituency for this
2514  * function probably doesn't want minus zero, force it to plain zero.
2515  */
2516  if (result == 0.0)
2517  result = 0.0;
2518 
2519  CHECKFLOATVAL(result, true /* tand(90) == Inf */ , true);
2520  PG_RETURN_FLOAT8(result);
2521 }
2522 
2523 
2524 /*
2525  * degrees - returns degrees converted from radians
2526  */
2527 Datum
2529 {
2530  float8 arg1 = PG_GETARG_FLOAT8(0);
2531  float8 result;
2532 
2533  result = arg1 / RADIANS_PER_DEGREE;
2534 
2535  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
2536  PG_RETURN_FLOAT8(result);
2537 }
2538 
2539 
2540 /*
2541  * dpi - returns the constant PI
2542  */
2543 Datum
2545 {
2547 }
2548 
2549 
2550 /*
2551  * radians - returns radians converted from degrees
2552  */
2553 Datum
2555 {
2556  float8 arg1 = PG_GETARG_FLOAT8(0);
2557  float8 result;
2558 
2559  result = arg1 * RADIANS_PER_DEGREE;
2560 
2561  CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
2562  PG_RETURN_FLOAT8(result);
2563 }
2564 
2565 
2566 /*
2567  * drandom - returns a random number
2568  */
2569 Datum
2571 {
2572  float8 result;
2573 
2574  /* result [0.0 - 1.0) */
2575  result = (double) random() / ((double) MAX_RANDOM_VALUE + 1);
2576 
2577  PG_RETURN_FLOAT8(result);
2578 }
2579 
2580 
2581 /*
2582  * setseed - set seed for the random number generator
2583  */
2584 Datum
2586 {
2587  float8 seed = PG_GETARG_FLOAT8(0);
2588  int iseed;
2589 
2590  if (seed < -1 || seed > 1)
2591  elog(ERROR, "setseed parameter %f out of range [-1,1]", seed);
2592 
2593  iseed = (int) (seed * MAX_RANDOM_VALUE);
2594  srandom((unsigned int) iseed);
2595 
2596  PG_RETURN_VOID();
2597 }
2598 
2599 
2600 
2601 /*
2602  * =========================
2603  * FLOAT AGGREGATE OPERATORS
2604  * =========================
2605  *
2606  * float8_accum - accumulate for AVG(), variance aggregates, etc.
2607  * float4_accum - same, but input data is float4
2608  * float8_avg - produce final result for float AVG()
2609  * float8_var_samp - produce final result for float VAR_SAMP()
2610  * float8_var_pop - produce final result for float VAR_POP()
2611  * float8_stddev_samp - produce final result for float STDDEV_SAMP()
2612  * float8_stddev_pop - produce final result for float STDDEV_POP()
2613  *
2614  * The transition datatype for all these aggregates is a 3-element array
2615  * of float8, holding the values N, sum(X), sum(X*X) in that order.
2616  *
2617  * Note that we represent N as a float to avoid having to build a special
2618  * datatype. Given a reasonable floating-point implementation, there should
2619  * be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the
2620  * user will have doubtless lost interest anyway...)
2621  */
2622 
2623 static float8 *
2624 check_float8_array(ArrayType *transarray, const char *caller, int n)
2625 {
2626  /*
2627  * We expect the input to be an N-element float array; verify that. We
2628  * don't need to use deconstruct_array() since the array data is just
2629  * going to look like a C array of N float8 values.
2630  */
2631  if (ARR_NDIM(transarray) != 1 ||
2632  ARR_DIMS(transarray)[0] != n ||
2633  ARR_HASNULL(transarray) ||
2634  ARR_ELEMTYPE(transarray) != FLOAT8OID)
2635  elog(ERROR, "%s: expected %d-element float8 array", caller, n);
2636  return (float8 *) ARR_DATA_PTR(transarray);
2637 }
2638 
2639 /*
2640  * float8_combine
2641  *
2642  * An aggregate combine function used to combine two 3 fields
2643  * aggregate transition data into a single transition data.
2644  * This function is used only in two stage aggregation and
2645  * shouldn't be called outside aggregate context.
2646  */
2647 Datum
2649 {
2650  ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
2651  ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
2652  float8 *transvalues1;
2653  float8 *transvalues2;
2654  float8 N,
2655  sumX,
2656  sumX2;
2657 
2658  if (!AggCheckCallContext(fcinfo, NULL))
2659  elog(ERROR, "aggregate function called in non-aggregate context");
2660 
2661  transvalues1 = check_float8_array(transarray1, "float8_combine", 3);
2662  N = transvalues1[0];
2663  sumX = transvalues1[1];
2664  sumX2 = transvalues1[2];
2665 
2666  transvalues2 = check_float8_array(transarray2, "float8_combine", 3);
2667 
2668  N += transvalues2[0];
2669  sumX += transvalues2[1];
2670  CHECKFLOATVAL(sumX, isinf(transvalues1[1]) || isinf(transvalues2[1]),
2671  true);
2672  sumX2 += transvalues2[2];
2673  CHECKFLOATVAL(sumX2, isinf(transvalues1[2]) || isinf(transvalues2[2]),
2674  true);
2675 
2676  transvalues1[0] = N;
2677  transvalues1[1] = sumX;
2678  transvalues1[2] = sumX2;
2679 
2680  PG_RETURN_ARRAYTYPE_P(transarray1);
2681 }
2682 
2683 Datum
2685 {
2686  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2688  float8 *transvalues;
2689  float8 N,
2690  sumX,
2691  sumX2;
2692 
2693  transvalues = check_float8_array(transarray, "float8_accum", 3);
2694  N = transvalues[0];
2695  sumX = transvalues[1];
2696  sumX2 = transvalues[2];
2697 
2698  N += 1.0;
2699  sumX += newval;
2700  CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
2701  sumX2 += newval * newval;
2702  CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
2703 
2704  /*
2705  * If we're invoked as an aggregate, we can cheat and modify our first
2706  * parameter in-place to reduce palloc overhead. Otherwise we construct a
2707  * new array with the updated transition data and return it.
2708  */
2709  if (AggCheckCallContext(fcinfo, NULL))
2710  {
2711  transvalues[0] = N;
2712  transvalues[1] = sumX;
2713  transvalues[2] = sumX2;
2714 
2715  PG_RETURN_ARRAYTYPE_P(transarray);
2716  }
2717  else
2718  {
2719  Datum transdatums[3];
2720  ArrayType *result;
2721 
2722  transdatums[0] = Float8GetDatumFast(N);
2723  transdatums[1] = Float8GetDatumFast(sumX);
2724  transdatums[2] = Float8GetDatumFast(sumX2);
2725 
2726  result = construct_array(transdatums, 3,
2727  FLOAT8OID,
2728  sizeof(float8), FLOAT8PASSBYVAL, 'd');
2729 
2730  PG_RETURN_ARRAYTYPE_P(result);
2731  }
2732 }
2733 
2734 Datum
2736 {
2737  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2738 
2739  /* do computations as float8 */
2741  float8 *transvalues;
2742  float8 N,
2743  sumX,
2744  sumX2;
2745 
2746  transvalues = check_float8_array(transarray, "float4_accum", 3);
2747  N = transvalues[0];
2748  sumX = transvalues[1];
2749  sumX2 = transvalues[2];
2750 
2751  N += 1.0;
2752  sumX += newval;
2753  CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
2754  sumX2 += newval * newval;
2755  CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
2756 
2757  /*
2758  * If we're invoked as an aggregate, we can cheat and modify our first
2759  * parameter in-place to reduce palloc overhead. Otherwise we construct a
2760  * new array with the updated transition data and return it.
2761  */
2762  if (AggCheckCallContext(fcinfo, NULL))
2763  {
2764  transvalues[0] = N;
2765  transvalues[1] = sumX;
2766  transvalues[2] = sumX2;
2767 
2768  PG_RETURN_ARRAYTYPE_P(transarray);
2769  }
2770  else
2771  {
2772  Datum transdatums[3];
2773  ArrayType *result;
2774 
2775  transdatums[0] = Float8GetDatumFast(N);
2776  transdatums[1] = Float8GetDatumFast(sumX);
2777  transdatums[2] = Float8GetDatumFast(sumX2);
2778 
2779  result = construct_array(transdatums, 3,
2780  FLOAT8OID,
2781  sizeof(float8), FLOAT8PASSBYVAL, 'd');
2782 
2783  PG_RETURN_ARRAYTYPE_P(result);
2784  }
2785 }
2786 
2787 Datum
2789 {
2790  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2791  float8 *transvalues;
2792  float8 N,
2793  sumX;
2794 
2795  transvalues = check_float8_array(transarray, "float8_avg", 3);
2796  N = transvalues[0];
2797  sumX = transvalues[1];
2798  /* ignore sumX2 */
2799 
2800  /* SQL defines AVG of no values to be NULL */
2801  if (N == 0.0)
2802  PG_RETURN_NULL();
2803 
2804  PG_RETURN_FLOAT8(sumX / N);
2805 }
2806 
2807 Datum
2809 {
2810  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2811  float8 *transvalues;
2812  float8 N,
2813  sumX,
2814  sumX2,
2815  numerator;
2816 
2817  transvalues = check_float8_array(transarray, "float8_var_pop", 3);
2818  N = transvalues[0];
2819  sumX = transvalues[1];
2820  sumX2 = transvalues[2];
2821 
2822  /* Population variance is undefined when N is 0, so return NULL */
2823  if (N == 0.0)
2824  PG_RETURN_NULL();
2825 
2826  numerator = N * sumX2 - sumX * sumX;
2827  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2828 
2829  /* Watch out for roundoff error producing a negative numerator */
2830  if (numerator <= 0.0)
2831  PG_RETURN_FLOAT8(0.0);
2832 
2833  PG_RETURN_FLOAT8(numerator / (N * N));
2834 }
2835 
2836 Datum
2838 {
2839  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2840  float8 *transvalues;
2841  float8 N,
2842  sumX,
2843  sumX2,
2844  numerator;
2845 
2846  transvalues = check_float8_array(transarray, "float8_var_samp", 3);
2847  N = transvalues[0];
2848  sumX = transvalues[1];
2849  sumX2 = transvalues[2];
2850 
2851  /* Sample variance is undefined when N is 0 or 1, so return NULL */
2852  if (N <= 1.0)
2853  PG_RETURN_NULL();
2854 
2855  numerator = N * sumX2 - sumX * sumX;
2856  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2857 
2858  /* Watch out for roundoff error producing a negative numerator */
2859  if (numerator <= 0.0)
2860  PG_RETURN_FLOAT8(0.0);
2861 
2862  PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
2863 }
2864 
2865 Datum
2867 {
2868  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2869  float8 *transvalues;
2870  float8 N,
2871  sumX,
2872  sumX2,
2873  numerator;
2874 
2875  transvalues = check_float8_array(transarray, "float8_stddev_pop", 3);
2876  N = transvalues[0];
2877  sumX = transvalues[1];
2878  sumX2 = transvalues[2];
2879 
2880  /* Population stddev is undefined when N is 0, so return NULL */
2881  if (N == 0.0)
2882  PG_RETURN_NULL();
2883 
2884  numerator = N * sumX2 - sumX * sumX;
2885  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2886 
2887  /* Watch out for roundoff error producing a negative numerator */
2888  if (numerator <= 0.0)
2889  PG_RETURN_FLOAT8(0.0);
2890 
2891  PG_RETURN_FLOAT8(sqrt(numerator / (N * N)));
2892 }
2893 
2894 Datum
2896 {
2897  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2898  float8 *transvalues;
2899  float8 N,
2900  sumX,
2901  sumX2,
2902  numerator;
2903 
2904  transvalues = check_float8_array(transarray, "float8_stddev_samp", 3);
2905  N = transvalues[0];
2906  sumX = transvalues[1];
2907  sumX2 = transvalues[2];
2908 
2909  /* Sample stddev is undefined when N is 0 or 1, so return NULL */
2910  if (N <= 1.0)
2911  PG_RETURN_NULL();
2912 
2913  numerator = N * sumX2 - sumX * sumX;
2914  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
2915 
2916  /* Watch out for roundoff error producing a negative numerator */
2917  if (numerator <= 0.0)
2918  PG_RETURN_FLOAT8(0.0);
2919 
2920  PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));
2921 }
2922 
2923 /*
2924  * =========================
2925  * SQL2003 BINARY AGGREGATES
2926  * =========================
2927  *
2928  * The transition datatype for all these aggregates is a 6-element array of
2929  * float8, holding the values N, sum(X), sum(X*X), sum(Y), sum(Y*Y), sum(X*Y)
2930  * in that order. Note that Y is the first argument to the aggregates!
2931  *
2932  * It might seem attractive to optimize this by having multiple accumulator
2933  * functions that only calculate the sums actually needed. But on most
2934  * modern machines, a couple of extra floating-point multiplies will be
2935  * insignificant compared to the other per-tuple overhead, so I've chosen
2936  * to minimize code space instead.
2937  */
2938 
2939 Datum
2941 {
2942  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2943  float8 newvalY = PG_GETARG_FLOAT8(1);
2944  float8 newvalX = PG_GETARG_FLOAT8(2);
2945  float8 *transvalues;
2946  float8 N,
2947  sumX,
2948  sumX2,
2949  sumY,
2950  sumY2,
2951  sumXY;
2952 
2953  transvalues = check_float8_array(transarray, "float8_regr_accum", 6);
2954  N = transvalues[0];
2955  sumX = transvalues[1];
2956  sumX2 = transvalues[2];
2957  sumY = transvalues[3];
2958  sumY2 = transvalues[4];
2959  sumXY = transvalues[5];
2960 
2961  N += 1.0;
2962  sumX += newvalX;
2963  CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newvalX), true);
2964  sumX2 += newvalX * newvalX;
2965  CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newvalX), true);
2966  sumY += newvalY;
2967  CHECKFLOATVAL(sumY, isinf(transvalues[3]) || isinf(newvalY), true);
2968  sumY2 += newvalY * newvalY;
2969  CHECKFLOATVAL(sumY2, isinf(transvalues[4]) || isinf(newvalY), true);
2970  sumXY += newvalX * newvalY;
2971  CHECKFLOATVAL(sumXY, isinf(transvalues[5]) || isinf(newvalX) ||
2972  isinf(newvalY), true);
2973 
2974  /*
2975  * If we're invoked as an aggregate, we can cheat and modify our first
2976  * parameter in-place to reduce palloc overhead. Otherwise we construct a
2977  * new array with the updated transition data and return it.
2978  */
2979  if (AggCheckCallContext(fcinfo, NULL))
2980  {
2981  transvalues[0] = N;
2982  transvalues[1] = sumX;
2983  transvalues[2] = sumX2;
2984  transvalues[3] = sumY;
2985  transvalues[4] = sumY2;
2986  transvalues[5] = sumXY;
2987 
2988  PG_RETURN_ARRAYTYPE_P(transarray);
2989  }
2990  else
2991  {
2992  Datum transdatums[6];
2993  ArrayType *result;
2994 
2995  transdatums[0] = Float8GetDatumFast(N);
2996  transdatums[1] = Float8GetDatumFast(sumX);
2997  transdatums[2] = Float8GetDatumFast(sumX2);
2998  transdatums[3] = Float8GetDatumFast(sumY);
2999  transdatums[4] = Float8GetDatumFast(sumY2);
3000  transdatums[5] = Float8GetDatumFast(sumXY);
3001 
3002  result = construct_array(transdatums, 6,
3003  FLOAT8OID,
3004  sizeof(float8), FLOAT8PASSBYVAL, 'd');
3005 
3006  PG_RETURN_ARRAYTYPE_P(result);
3007  }
3008 }
3009 
3010 /*
3011  * float8_regr_combine
3012  *
3013  * An aggregate combine function used to combine two 6 fields
3014  * aggregate transition data into a single transition data.
3015  * This function is used only in two stage aggregation and
3016  * shouldn't be called outside aggregate context.
3017  */
3018 Datum
3020 {
3021  ArrayType *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
3022  ArrayType *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
3023  float8 *transvalues1;
3024  float8 *transvalues2;
3025  float8 N,
3026  sumX,
3027  sumX2,
3028  sumY,
3029  sumY2,
3030  sumXY;
3031 
3032  if (!AggCheckCallContext(fcinfo, NULL))
3033  elog(ERROR, "aggregate function called in non-aggregate context");
3034 
3035  transvalues1 = check_float8_array(transarray1, "float8_regr_combine", 6);
3036  N = transvalues1[0];
3037  sumX = transvalues1[1];
3038  sumX2 = transvalues1[2];
3039  sumY = transvalues1[3];
3040  sumY2 = transvalues1[4];
3041  sumXY = transvalues1[5];
3042 
3043  transvalues2 = check_float8_array(transarray2, "float8_regr_combine", 6);
3044 
3045  N += transvalues2[0];
3046  sumX += transvalues2[1];
3047  CHECKFLOATVAL(sumX, isinf(transvalues1[1]) || isinf(transvalues2[1]),
3048  true);
3049  sumX2 += transvalues2[2];
3050  CHECKFLOATVAL(sumX2, isinf(transvalues1[2]) || isinf(transvalues2[2]),
3051  true);
3052  sumY += transvalues2[3];
3053  CHECKFLOATVAL(sumY, isinf(transvalues1[3]) || isinf(transvalues2[3]),
3054  true);
3055  sumY2 += transvalues2[4];
3056  CHECKFLOATVAL(sumY2, isinf(transvalues1[4]) || isinf(transvalues2[4]),
3057  true);
3058  sumXY += transvalues2[5];
3059  CHECKFLOATVAL(sumXY, isinf(transvalues1[5]) || isinf(transvalues2[5]),
3060  true);
3061 
3062  transvalues1[0] = N;
3063  transvalues1[1] = sumX;
3064  transvalues1[2] = sumX2;
3065  transvalues1[3] = sumY;
3066  transvalues1[4] = sumY2;
3067  transvalues1[5] = sumXY;
3068 
3069  PG_RETURN_ARRAYTYPE_P(transarray1);
3070 }
3071 
3072 
3073 Datum
3075 {
3076  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3077  float8 *transvalues;
3078  float8 N,
3079  sumX,
3080  sumX2,
3081  numerator;
3082 
3083  transvalues = check_float8_array(transarray, "float8_regr_sxx", 6);
3084  N = transvalues[0];
3085  sumX = transvalues[1];
3086  sumX2 = transvalues[2];
3087 
3088  /* if N is 0 we should return NULL */
3089  if (N < 1.0)
3090  PG_RETURN_NULL();
3091 
3092  numerator = N * sumX2 - sumX * sumX;
3093  CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
3094 
3095  /* Watch out for roundoff error producing a negative numerator */
3096  if (numerator <= 0.0)
3097  PG_RETURN_FLOAT8(0.0);
3098 
3099  PG_RETURN_FLOAT8(numerator / N);
3100 }
3101 
3102 Datum
3104 {
3105  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3106  float8 *transvalues;
3107  float8 N,
3108  sumY,
3109  sumY2,
3110  numerator;
3111 
3112  transvalues = check_float8_array(transarray, "float8_regr_syy", 6);
3113  N = transvalues[0];
3114  sumY = transvalues[3];
3115  sumY2 = transvalues[4];
3116 
3117  /* if N is 0 we should return NULL */
3118  if (N < 1.0)
3119  PG_RETURN_NULL();
3120 
3121  numerator = N * sumY2 - sumY * sumY;
3122  CHECKFLOATVAL(numerator, isinf(sumY2) || isinf(sumY), true);
3123 
3124  /* Watch out for roundoff error producing a negative numerator */
3125  if (numerator <= 0.0)
3126  PG_RETURN_FLOAT8(0.0);
3127 
3128  PG_RETURN_FLOAT8(numerator / N);
3129 }
3130 
3131 Datum
3133 {
3134  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3135  float8 *transvalues;
3136  float8 N,
3137  sumX,
3138  sumY,
3139  sumXY,
3140  numerator;
3141 
3142  transvalues = check_float8_array(transarray, "float8_regr_sxy", 6);
3143  N = transvalues[0];
3144  sumX = transvalues[1];
3145  sumY = transvalues[3];
3146  sumXY = transvalues[5];
3147 
3148  /* if N is 0 we should return NULL */
3149  if (N < 1.0)
3150  PG_RETURN_NULL();
3151 
3152  numerator = N * sumXY - sumX * sumY;
3153  CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
3154  isinf(sumY), true);
3155 
3156  /* A negative result is valid here */
3157 
3158  PG_RETURN_FLOAT8(numerator / N);
3159 }
3160 
3161 Datum
3163 {
3164  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3165  float8 *transvalues;
3166  float8 N,
3167  sumX;
3168 
3169  transvalues = check_float8_array(transarray, "float8_regr_avgx", 6);
3170  N = transvalues[0];
3171  sumX = transvalues[1];
3172 
3173  /* if N is 0 we should return NULL */
3174  if (N < 1.0)
3175  PG_RETURN_NULL();
3176 
3177  PG_RETURN_FLOAT8(sumX / N);
3178 }
3179 
3180 Datum
3182 {
3183  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3184  float8 *transvalues;
3185  float8 N,
3186  sumY;
3187 
3188  transvalues = check_float8_array(transarray, "float8_regr_avgy", 6);
3189  N = transvalues[0];
3190  sumY = transvalues[3];
3191 
3192  /* if N is 0 we should return NULL */
3193  if (N < 1.0)
3194  PG_RETURN_NULL();
3195 
3196  PG_RETURN_FLOAT8(sumY / N);
3197 }
3198 
3199 Datum
3201 {
3202  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3203  float8 *transvalues;
3204  float8 N,
3205  sumX,
3206  sumY,
3207  sumXY,
3208  numerator;
3209 
3210  transvalues = check_float8_array(transarray, "float8_covar_pop", 6);
3211  N = transvalues[0];
3212  sumX = transvalues[1];
3213  sumY = transvalues[3];
3214  sumXY = transvalues[5];
3215 
3216  /* if N is 0 we should return NULL */
3217  if (N < 1.0)
3218  PG_RETURN_NULL();
3219 
3220  numerator = N * sumXY - sumX * sumY;
3221  CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
3222  isinf(sumY), true);
3223 
3224  PG_RETURN_FLOAT8(numerator / (N * N));
3225 }
3226 
3227 Datum
3229 {
3230  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3231  float8 *transvalues;
3232  float8 N,
3233  sumX,
3234  sumY,
3235  sumXY,
3236  numerator;
3237 
3238  transvalues = check_float8_array(transarray, "float8_covar_samp", 6);
3239  N = transvalues[0];
3240  sumX = transvalues[1];
3241  sumY = transvalues[3];
3242  sumXY = transvalues[5];
3243 
3244  /* if N is <= 1 we should return NULL */
3245  if (N < 2.0)
3246  PG_RETURN_NULL();
3247 
3248  numerator = N * sumXY - sumX * sumY;
3249  CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
3250  isinf(sumY), true);
3251 
3252  PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
3253 }
3254 
3255 Datum
3257 {
3258  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3259  float8 *transvalues;
3260  float8 N,
3261  sumX,
3262  sumX2,
3263  sumY,
3264  sumY2,
3265  sumXY,
3266  numeratorX,
3267  numeratorY,
3268  numeratorXY;
3269 
3270  transvalues = check_float8_array(transarray, "float8_corr", 6);
3271  N = transvalues[0];
3272  sumX = transvalues[1];
3273  sumX2 = transvalues[2];
3274  sumY = transvalues[3];
3275  sumY2 = transvalues[4];
3276  sumXY = transvalues[5];
3277 
3278  /* if N is 0 we should return NULL */
3279  if (N < 1.0)
3280  PG_RETURN_NULL();
3281 
3282  numeratorX = N * sumX2 - sumX * sumX;
3283  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3284  numeratorY = N * sumY2 - sumY * sumY;
3285  CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
3286  numeratorXY = N * sumXY - sumX * sumY;
3287  CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
3288  isinf(sumY), true);
3289  if (numeratorX <= 0 || numeratorY <= 0)
3290  PG_RETURN_NULL();
3291 
3292  PG_RETURN_FLOAT8(numeratorXY / sqrt(numeratorX * numeratorY));
3293 }
3294 
3295 Datum
3297 {
3298  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3299  float8 *transvalues;
3300  float8 N,
3301  sumX,
3302  sumX2,
3303  sumY,
3304  sumY2,
3305  sumXY,
3306  numeratorX,
3307  numeratorY,
3308  numeratorXY;
3309 
3310  transvalues = check_float8_array(transarray, "float8_regr_r2", 6);
3311  N = transvalues[0];
3312  sumX = transvalues[1];
3313  sumX2 = transvalues[2];
3314  sumY = transvalues[3];
3315  sumY2 = transvalues[4];
3316  sumXY = transvalues[5];
3317 
3318  /* if N is 0 we should return NULL */
3319  if (N < 1.0)
3320  PG_RETURN_NULL();
3321 
3322  numeratorX = N * sumX2 - sumX * sumX;
3323  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3324  numeratorY = N * sumY2 - sumY * sumY;
3325  CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
3326  numeratorXY = N * sumXY - sumX * sumY;
3327  CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
3328  isinf(sumY), true);
3329  if (numeratorX <= 0)
3330  PG_RETURN_NULL();
3331  /* per spec, horizontal line produces 1.0 */
3332  if (numeratorY <= 0)
3333  PG_RETURN_FLOAT8(1.0);
3334 
3335  PG_RETURN_FLOAT8((numeratorXY * numeratorXY) /
3336  (numeratorX * numeratorY));
3337 }
3338 
3339 Datum
3341 {
3342  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3343  float8 *transvalues;
3344  float8 N,
3345  sumX,
3346  sumX2,
3347  sumY,
3348  sumXY,
3349  numeratorX,
3350  numeratorXY;
3351 
3352  transvalues = check_float8_array(transarray, "float8_regr_slope", 6);
3353  N = transvalues[0];
3354  sumX = transvalues[1];
3355  sumX2 = transvalues[2];
3356  sumY = transvalues[3];
3357  sumXY = transvalues[5];
3358 
3359  /* if N is 0 we should return NULL */
3360  if (N < 1.0)
3361  PG_RETURN_NULL();
3362 
3363  numeratorX = N * sumX2 - sumX * sumX;
3364  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3365  numeratorXY = N * sumXY - sumX * sumY;
3366  CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
3367  isinf(sumY), true);
3368  if (numeratorX <= 0)
3369  PG_RETURN_NULL();
3370 
3371  PG_RETURN_FLOAT8(numeratorXY / numeratorX);
3372 }
3373 
3374 Datum
3376 {
3377  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
3378  float8 *transvalues;
3379  float8 N,
3380  sumX,
3381  sumX2,
3382  sumY,
3383  sumXY,
3384  numeratorX,
3385  numeratorXXY;
3386 
3387  transvalues = check_float8_array(transarray, "float8_regr_intercept", 6);
3388  N = transvalues[0];
3389  sumX = transvalues[1];
3390  sumX2 = transvalues[2];
3391  sumY = transvalues[3];
3392  sumXY = transvalues[5];
3393 
3394  /* if N is 0 we should return NULL */
3395  if (N < 1.0)
3396  PG_RETURN_NULL();
3397 
3398  numeratorX = N * sumX2 - sumX * sumX;
3399  CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
3400  numeratorXXY = sumY * sumX2 - sumX * sumXY;
3401  CHECKFLOATVAL(numeratorXXY, isinf(sumY) || isinf(sumX2) ||
3402  isinf(sumX) || isinf(sumXY), true);
3403  if (numeratorX <= 0)
3404  PG_RETURN_NULL();
3405 
3406  PG_RETURN_FLOAT8(numeratorXXY / numeratorX);
3407 }
3408 
3409 
3410 /*
3411  * ====================================
3412  * MIXED-PRECISION ARITHMETIC OPERATORS
3413  * ====================================
3414  */
3415 
3416 /*
3417  * float48pl - returns arg1 + arg2
3418  * float48mi - returns arg1 - arg2
3419  * float48mul - returns arg1 * arg2
3420  * float48div - returns arg1 / arg2
3421  */
3422 Datum
3424 {
3425  float4 arg1 = PG_GETARG_FLOAT4(0);
3426  float8 arg2 = PG_GETARG_FLOAT8(1);
3427  float8 result;
3428 
3429  result = arg1 + arg2;
3430  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3431  PG_RETURN_FLOAT8(result);
3432 }
3433 
3434 Datum
3436 {
3437  float4 arg1 = PG_GETARG_FLOAT4(0);
3438  float8 arg2 = PG_GETARG_FLOAT8(1);
3439  float8 result;
3440 
3441  result = arg1 - arg2;
3442  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3443  PG_RETURN_FLOAT8(result);
3444 }
3445 
3446 Datum
3448 {
3449  float4 arg1 = PG_GETARG_FLOAT4(0);
3450  float8 arg2 = PG_GETARG_FLOAT8(1);
3451  float8 result;
3452 
3453  result = arg1 * arg2;
3454  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
3455  arg1 == 0 || arg2 == 0);
3456  PG_RETURN_FLOAT8(result);
3457 }
3458 
3459 Datum
3461 {
3462  float4 arg1 = PG_GETARG_FLOAT4(0);
3463  float8 arg2 = PG_GETARG_FLOAT8(1);
3464  float8 result;
3465 
3466  if (arg2 == 0.0)
3467  ereport(ERROR,
3468  (errcode(ERRCODE_DIVISION_BY_ZERO),
3469  errmsg("division by zero")));
3470 
3471  result = arg1 / arg2;
3472  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
3473  PG_RETURN_FLOAT8(result);
3474 }
3475 
3476 /*
3477  * float84pl - returns arg1 + arg2
3478  * float84mi - returns arg1 - arg2
3479  * float84mul - returns arg1 * arg2
3480  * float84div - returns arg1 / arg2
3481  */
3482 Datum
3484 {
3485  float8 arg1 = PG_GETARG_FLOAT8(0);
3486  float4 arg2 = PG_GETARG_FLOAT4(1);
3487  float8 result;
3488 
3489  result = arg1 + arg2;
3490 
3491  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3492  PG_RETURN_FLOAT8(result);
3493 }
3494 
3495 Datum
3497 {
3498  float8 arg1 = PG_GETARG_FLOAT8(0);
3499  float4 arg2 = PG_GETARG_FLOAT4(1);
3500  float8 result;
3501 
3502  result = arg1 - arg2;
3503 
3504  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
3505  PG_RETURN_FLOAT8(result);
3506 }
3507 
3508 Datum
3510 {
3511  float8 arg1 = PG_GETARG_FLOAT8(0);
3512  float4 arg2 = PG_GETARG_FLOAT4(1);
3513  float8 result;
3514 
3515  result = arg1 * arg2;
3516 
3517  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
3518  arg1 == 0 || arg2 == 0);
3519  PG_RETURN_FLOAT8(result);
3520 }
3521 
3522 Datum
3524 {
3525  float8 arg1 = PG_GETARG_FLOAT8(0);
3526  float4 arg2 = PG_GETARG_FLOAT4(1);
3527  float8 result;
3528 
3529  if (arg2 == 0.0)
3530  ereport(ERROR,
3531  (errcode(ERRCODE_DIVISION_BY_ZERO),
3532  errmsg("division by zero")));
3533 
3534  result = arg1 / arg2;
3535 
3536  CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
3537  PG_RETURN_FLOAT8(result);
3538 }
3539 
3540 /*
3541  * ====================
3542  * COMPARISON OPERATORS
3543  * ====================
3544  */
3545 
3546 /*
3547  * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
3548  */
3549 Datum
3551 {
3552  float4 arg1 = PG_GETARG_FLOAT4(0);
3553  float8 arg2 = PG_GETARG_FLOAT8(1);
3554 
3555  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
3556 }
3557 
3558 Datum
3560 {
3561  float4 arg1 = PG_GETARG_FLOAT4(0);
3562  float8 arg2 = PG_GETARG_FLOAT8(1);
3563 
3564  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
3565 }
3566 
3567 Datum
3569 {
3570  float4 arg1 = PG_GETARG_FLOAT4(0);
3571  float8 arg2 = PG_GETARG_FLOAT8(1);
3572 
3573  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
3574 }
3575 
3576 Datum
3578 {
3579  float4 arg1 = PG_GETARG_FLOAT4(0);
3580  float8 arg2 = PG_GETARG_FLOAT8(1);
3581 
3582  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
3583 }
3584 
3585 Datum
3587 {
3588  float4 arg1 = PG_GETARG_FLOAT4(0);
3589  float8 arg2 = PG_GETARG_FLOAT8(1);
3590 
3591  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
3592 }
3593 
3594 Datum
3596 {
3597  float4 arg1 = PG_GETARG_FLOAT4(0);
3598  float8 arg2 = PG_GETARG_FLOAT8(1);
3599 
3600  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
3601 }
3602 
3603 /*
3604  * float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
3605  */
3606 Datum
3608 {
3609  float8 arg1 = PG_GETARG_FLOAT8(0);
3610  float4 arg2 = PG_GETARG_FLOAT4(1);
3611 
3612  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
3613 }
3614 
3615 Datum
3617 {
3618  float8 arg1 = PG_GETARG_FLOAT8(0);
3619  float4 arg2 = PG_GETARG_FLOAT4(1);
3620 
3621  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
3622 }
3623 
3624 Datum
3626 {
3627  float8 arg1 = PG_GETARG_FLOAT8(0);
3628  float4 arg2 = PG_GETARG_FLOAT4(1);
3629 
3630  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
3631 }
3632 
3633 Datum
3635 {
3636  float8 arg1 = PG_GETARG_FLOAT8(0);
3637  float4 arg2 = PG_GETARG_FLOAT4(1);
3638 
3639  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
3640 }
3641 
3642 Datum
3644 {
3645  float8 arg1 = PG_GETARG_FLOAT8(0);
3646  float4 arg2 = PG_GETARG_FLOAT4(1);
3647 
3648  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
3649 }
3650 
3651 Datum
3653 {
3654  float8 arg1 = PG_GETARG_FLOAT8(0);
3655  float4 arg2 = PG_GETARG_FLOAT4(1);
3656 
3657  PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
3658 }
3659 
3660 /*
3661  * Implements the float8 version of the width_bucket() function
3662  * defined by SQL2003. See also width_bucket_numeric().
3663  *
3664  * 'bound1' and 'bound2' are the lower and upper bounds of the
3665  * histogram's range, respectively. 'count' is the number of buckets
3666  * in the histogram. width_bucket() returns an integer indicating the
3667  * bucket number that 'operand' belongs to in an equiwidth histogram
3668  * with the specified characteristics. An operand smaller than the
3669  * lower bound is assigned to bucket 0. An operand greater than the
3670  * upper bound is assigned to an additional bucket (with number
3671  * count+1). We don't allow "NaN" for any of the float8 inputs, and we
3672  * don't allow either of the histogram bounds to be +/- infinity.
3673  */
3674 Datum
3676 {
3677  float8 operand = PG_GETARG_FLOAT8(0);
3678  float8 bound1 = PG_GETARG_FLOAT8(1);
3679  float8 bound2 = PG_GETARG_FLOAT8(2);
3680  int32 count = PG_GETARG_INT32(3);
3681  int32 result;
3682 
3683  if (count <= 0.0)
3684  ereport(ERROR,
3685  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3686  errmsg("count must be greater than zero")));
3687 
3688  if (isnan(operand) || isnan(bound1) || isnan(bound2))
3689  ereport(ERROR,
3690  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3691  errmsg("operand, lower bound, and upper bound cannot be NaN")));
3692 
3693  /* Note that we allow "operand" to be infinite */
3694  if (isinf(bound1) || isinf(bound2))
3695  ereport(ERROR,
3696  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3697  errmsg("lower and upper bounds must be finite")));
3698 
3699  if (bound1 < bound2)
3700  {
3701  if (operand < bound1)
3702  result = 0;
3703  else if (operand >= bound2)
3704  {
3705  if (pg_add_s32_overflow(count, 1, &result))
3706  ereport(ERROR,
3707  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3708  errmsg("integer out of range")));
3709  }
3710  else
3711  result = ((float8) count * (operand - bound1) / (bound2 - bound1)) + 1;
3712  }
3713  else if (bound1 > bound2)
3714  {
3715  if (operand > bound1)
3716  result = 0;
3717  else if (operand <= bound2)
3718  {
3719  if (pg_add_s32_overflow(count, 1, &result))
3720  ereport(ERROR,
3721  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3722  errmsg("integer out of range")));
3723  }
3724  else
3725  result = ((float8) count * (bound1 - operand) / (bound1 - bound2)) + 1;
3726  }
3727  else
3728  {
3729  ereport(ERROR,
3730  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
3731  errmsg("lower bound cannot equal upper bound")));
3732  result = 0; /* keep the compiler quiet */
3733  }
3734 
3735  PG_RETURN_INT32(result);
3736 }
3737 
3738 /* ========== PRIVATE ROUTINES ========== */
3739 
3740 #ifndef HAVE_CBRT
3741 
3742 static double
3743 cbrt(double x)
3744 {
3745  int isneg = (x < 0.0);
3746  double absx = fabs(x);
3747  double tmpres = pow(absx, (double) 1.0 / (double) 3.0);
3748 
3749  /*
3750  * The result is somewhat inaccurate --- not really pow()'s fault, as the
3751  * exponent it's handed contains roundoff error. We can improve the
3752  * accuracy by doing one iteration of Newton's formula. Beware of zero
3753  * input however.
3754  */
3755  if (tmpres > 0.0)
3756  tmpres -= (tmpres - absx / (tmpres * tmpres)) / (double) 3.0;
3757 
3758  return isneg ? -tmpres : tmpres;
3759 }
3760 
3761 #endif /* !HAVE_CBRT */
Datum float48lt(PG_FUNCTION_ARGS)
Definition: float.c:3568
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
Datum float8ne(PG_FUNCTION_ARGS)
Definition: float.c:1088
Datum dtoi2(PG_FUNCTION_ARGS)
Definition: float.c:1374
#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:1684
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:3652
Datum dcos(PG_FUNCTION_ARGS)
Definition: float.c:1853
float8 degree_c_sixty
Definition: float.c:85
Datum dacos(PG_FUNCTION_ARGS)
Definition: float.c:1743
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define cbrt
Definition: float.c:103
Datum radians(PG_FUNCTION_ARGS)
Definition: float.c:2554
Datum float8_stddev_pop(PG_FUNCTION_ARGS)
Definition: float.c:2866
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:2291
Datum float8_regr_syy(PG_FUNCTION_ARGS)
Definition: float.c:3103
Datum float4le(PG_FUNCTION_ARGS)
Definition: float.c:992
Datum datand(PG_FUNCTION_ARGS)
Definition: float.c:2159
Datum float48mi(PG_FUNCTION_ARGS)
Definition: float.c:3435
#define INIT_DEGREE_CONSTANTS()
Definition: float.c:2012
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:3132
Datum dsin(PG_FUNCTION_ARGS)
Definition: float.c:1920
Datum float8gt(PG_FUNCTION_ARGS)
Definition: float.c:1115
Datum dpi(PG_FUNCTION_ARGS)
Definition: float.c:2544
Datum float48eq(PG_FUNCTION_ARGS)
Definition: float.c:3550
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:2029
Datum float8_var_samp(PG_FUNCTION_ARGS)
Definition: float.c:2837
static bool degree_consts_set
Definition: float.c:68
long random(void)
Definition: random.c:22
Datum i4tof(PG_FUNCTION_ARGS)
Definition: float.c:1449
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:1328
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:1593
Datum float84div(PG_FUNCTION_ARGS)
Definition: float.c:3523
float get_float4_nan(void)
Definition: float.c:176
static double sind_q1(double x)
Definition: float.c:2252
Datum float8up(PG_FUNCTION_ARGS)
Definition: float.c:749
Datum dtrunc(PG_FUNCTION_ARGS)
Definition: float.c:1539
#define PG_RETURN_INT32(x)
Definition: fmgr.h:319
Datum float8_covar_pop(PG_FUNCTION_ARGS)
Definition: float.c:3200
Datum float48le(PG_FUNCTION_ARGS)
Definition: float.c:3577
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:1491
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:1479
static float8 acos_0_5
Definition: float.c:72
Datum float8_regr_r2(PG_FUNCTION_ARGS)
Definition: float.c:3296
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
Datum float84ne(PG_FUNCTION_ARGS)
Definition: float.c:3616
float8 degree_c_thirty
Definition: float.c:83
static void init_degree_constants(void)
Definition: float.c:2000
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:3074
Datum drandom(PG_FUNCTION_ARGS)
Definition: float.c:2570
Datum dlog10(PG_FUNCTION_ARGS)
Definition: float.c:1713
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
Datum float8_avg(PG_FUNCTION_ARGS)
Definition: float.c:2788
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:3423
Datum float4_accum(PG_FUNCTION_ARGS)
Definition: float.c:2735
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:3595
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:3340
Datum datan2(PG_FUNCTION_ARGS)
Definition: float.c:1828
Datum ftoi2(PG_FUNCTION_ARGS)
Definition: float.c:1432
Datum dtof(PG_FUNCTION_ARGS)
Definition: float.c:1340
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:3483
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:2062
Datum dcbrt(PG_FUNCTION_ARGS)
Definition: float.c:1578
Datum setseed(PG_FUNCTION_ARGS)
Definition: float.c:2585
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:1773
#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:1354
Datum float8_regr_combine(PG_FUNCTION_ARGS)
Definition: float.c:3019
Datum float84mul(PG_FUNCTION_ARGS)
Definition: float.c:3509
#define MAX_RANDOM_VALUE
Datum datan(PG_FUNCTION_ARGS)
Definition: float.c:1803
static double cosd_0_to_60(double x)
Definition: float.c:2239
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:1415
#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:2409
#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:1503
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:1516
Datum float4mul(PG_FUNCTION_ARGS)
Definition: float.c:830
double get_float8_infinity(void)
Definition: float.c:118
Datum float8_covar_samp(PG_FUNCTION_ARGS)
Definition: float.c:3228
Datum float8lt(PG_FUNCTION_ARGS)
Definition: float.c:1097
Datum float8_regr_intercept(PG_FUNCTION_ARGS)
Definition: float.c:3375
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:2528
Datum float4out(PG_FUNCTION_ARGS)
Definition: float.c:356
Datum dcot(PG_FUNCTION_ARGS)
Definition: float.c:1893
float float4
Definition: c.h:457
Datum float48ne(PG_FUNCTION_ARGS)
Definition: float.c:3559
Datum float8recv(PG_FUNCTION_ARGS)
Definition: float.c:626
Datum float8_regr_avgx(PG_FUNCTION_ARGS)
Definition: float.c:3162
static double cosd_q1(double x)
Definition: float.c:2272
static double sind_0_to_30(double x)
Definition: float.c:2225
static float8 asin_0_5
Definition: float.c:71
Datum float8_accum(PG_FUNCTION_ARGS)
Definition: float.c:2684
#define DatumGetFloat8(X)
Definition: postgres.h:713
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
uintptr_t Datum
Definition: postgres.h:367
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:1665
Datum float84lt(PG_FUNCTION_ARGS)
Definition: float.c:3625
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
Datum dtand(PG_FUNCTION_ARGS)
Definition: float.c:2463
Datum float84mi(PG_FUNCTION_ARGS)
Definition: float.c:3496
Datum width_bucket_float8(PG_FUNCTION_ARGS)
Definition: float.c:3675
int extra_float_digits
Definition: float.c:65
Datum float8_var_pop(PG_FUNCTION_ARGS)
Definition: float.c:2808
Datum float8_regr_accum(PG_FUNCTION_ARGS)
Definition: float.c:2940
#define PG_RETURN_VOID()
Definition: fmgr.h:314
#define Float8GetDatumFast(X)
Definition: postgres.h:761
Datum btfloat8sortsupport(PG_FUNCTION_ARGS)
Definition: float.c:1151
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:490
#define DatumGetFloat4(X)
Definition: postgres.h:665
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:3643
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:1461
Datum float48mul(PG_FUNCTION_ARGS)
Definition: float.c:3447
#define ARR_NDIM(a)
Definition: array.h:275
Datum dasind(PG_FUNCTION_ARGS)
Definition: float.c:2124
int is_infinite(double val)
Definition: float.c:196
Datum float8_corr(PG_FUNCTION_ARGS)
Definition: float.c:3256
Datum dsqrt(PG_FUNCTION_ARGS)
Definition: float.c:1557
Datum datan2d(PG_FUNCTION_ARGS)
Definition: float.c:2189
Datum i4tod(PG_FUNCTION_ARGS)
Definition: float.c:1391
Datum float8_combine(PG_FUNCTION_ARGS)
Definition: float.c:2648
static float8 * check_float8_array(ArrayType *transarray, const char *caller, int n)
Definition: float.c:2624
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:2895
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:3634
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:3460
#define PG_FUNCTION_ARGS
Definition: fmgr.h:163
Datum dcotd(PG_FUNCTION_ARGS)
Definition: float.c:2344
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:3181
Datum float84eq(PG_FUNCTION_ARGS)
Definition: float.c:3607
Datum dacosd(PG_FUNCTION_ARGS)
Definition: float.c:2089
#define ARR_ELEMTYPE(a)
Definition: array.h:277
Datum float48gt(PG_FUNCTION_ARGS)
Definition: float.c:3586
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:1403
Datum dtan(PG_FUNCTION_ARGS)
Definition: float.c:1946
Datum in_range_float8_float8(PG_FUNCTION_ARGS)
Definition: float.c:1186
Datum btfloat4sortsupport(PG_FUNCTION_ARGS)
Definition: float.c:1037