LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - float.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 80.7 % 1361 1098 3 41 181 38 54 701 52 291 170 746 1 20
Current Date: 2023-04-08 17:13:01 Functions: 88.7 % 159 141 17 1 130 8 3 17 136 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 93.5 % 31 29 2 3 23 3 3
Legend: Lines: hit not hit (60,120] days: 95.7 % 23 22 1 22
(120,180] days: 100.0 % 6 6 6
(180,240] days: 100.0 % 1 1 1
(240..) days: 80.0 % 1300 1040 41 181 38 54 698 288 170 706
Function coverage date bins:
[..60] days: 50.0 % 4 2 2 2
(60,120] days: 100.0 % 4 4 4
(120,180] days: 100.0 % 1 1 1
(240..) days: 44.4 % 302 134 17 1 130 1 3 17 133

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

Generated by: LCOV version v1.16-55-g56c0a2a