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 15:15:32 Functions: 88.7 % 159 141 17 1 130 8 3 17 136 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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
      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
     117 UBC           0 : is_infinite(double val)
     118                 : {
     119               0 :     int         inf = isinf(val);
     120                 : 
     121               0 :     if (inf == 0)
     122               0 :         return 0;
     123               0 :     else if (val > 0)
     124               0 :         return 1;
     125                 :     else
     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
     163 CBC     2012330 : float4in(PG_FUNCTION_ARGS)
     164                 : {
     165         2012330 :     char       *num = PG_GETARG_CSTRING(0);
     166                 : 
     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                 : {
     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 */
     197 GIC     2017609 :     while (*num != '\0' && isspace((unsigned char) *num))
     198             105 :         num++;
     199                 : 
     200                 :     /*
     201 ECB             :      * Check for an empty-string input to begin with, to avoid the vagaries of
     202                 :      * strtod() on different platforms.
     203                 :      */
     204 GIC     2017504 :     if (*num == '\0')
     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                 : 
     210 GIC     2017498 :     errno = 0;
     211         2017498 :     val = strtof(num, &endptr);
     212                 : 
     213                 :     /* did we not see anything that looks like a double? */
     214         2017498 :     if (endptr == num || errno != 0)
     215                 :     {
     216 CBC          46 :         int         save_errno = errno;
     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.
     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                 :          */
     228 GIC          46 :         if (pg_strncasecmp(num, "NaN", 3) == 0)
     229 ECB             :         {
     230 LBC           0 :             val = get_float4_nan();
     231 UIC           0 :             endptr = num + 3;
     232                 :         }
     233 CBC          46 :         else if (pg_strncasecmp(num, "Infinity", 8) == 0)
     234                 :         {
     235 LBC           0 :             val = get_float4_infinity();
     236 UIC           0 :             endptr = num + 8;
     237                 :         }
     238 GIC          46 :         else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
     239                 :         {
     240 UIC           0 :             val = get_float4_infinity();
     241               0 :             endptr = num + 9;
     242                 :         }
     243 GIC          46 :         else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
     244                 :         {
     245 UIC           0 :             val = -get_float4_infinity();
     246               0 :             endptr = num + 9;
     247 ECB             :         }
     248 GIC          46 :         else if (pg_strncasecmp(num, "inf", 3) == 0)
     249 EUB             :         {
     250 UBC           0 :             val = get_float4_infinity();
     251 UIC           0 :             endptr = num + 3;
     252 ECB             :         }
     253 GIC          46 :         else if (pg_strncasecmp(num, "+inf", 4) == 0)
     254 EUB             :         {
     255 UBC           0 :             val = get_float4_infinity();
     256 UIC           0 :             endptr = num + 4;
     257 ECB             :         }
     258 GIC          46 :         else if (pg_strncasecmp(num, "-inf", 4) == 0)
     259 EUB             :         {
     260 UBC           0 :             val = -get_float4_infinity();
     261 UIC           0 :             endptr = num + 4;
     262 ECB             :         }
     263 GIC          46 :         else if (save_errno == ERANGE)
     264 EUB             :         {
     265                 :             /*
     266                 :              * Some platforms return ERANGE for denormalized numbers (those
     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
     269 EUB             :              * detect whether it's a "real" out-of-range condition by checking
     270                 :              * to see if the result is zero or huge.
     271                 :              */
     272 GIC          33 :             if (val == 0.0 ||
     273                 : #if !defined(HUGE_VALF)
     274                 :                 isinf(val)
     275 EUB             : #else
     276 GBC           6 :                 (val >= HUGE_VALF || val <= -HUGE_VALF)
     277                 : #endif
     278 ECB             :                 )
     279                 :             {
     280                 :                 /* see comments in float8in_internal for rationale */
     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),
     294 ECB             :                      errmsg("invalid input syntax for type %s: \"%s\"",
     295                 :                             type_name, orig_string)));
     296                 :     }
     297                 : 
     298                 :     /* skip trailing whitespace */
     299 GIC     2017551 :     while (*endptr != '\0' && isspace((unsigned char) *endptr))
     300              99 :         endptr++;
     301                 : 
     302                 :     /* report stopping point if wanted, else complain if not end of string */
     303 GNC     2017452 :     if (endptr_p)
     304 UNC           0 :         *endptr_p = endptr;
     305 GNC     2017452 :     else if (*endptr != '\0')
     306              18 :         ereturn(escontext, 0,
     307 ECB             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     308                 :                  errmsg("invalid input syntax for type %s: \"%s\"",
     309                 :                         type_name, orig_string)));
     310                 : 
     311 GNC     2017434 :     return val;
     312                 : }
     313                 : 
     314                 : /*
     315                 :  *      float4out       - converts a float4 number to a string
     316 ECB             :  *                        using a standard output format
     317                 :  */
     318                 : Datum
     319 GIC       18362 : float4out(PG_FUNCTION_ARGS)
     320                 : {
     321           18362 :     float4      num = PG_GETARG_FLOAT4(0);
     322           18362 :     char       *ascii = (char *) palloc(32);
     323 CBC       18362 :     int         ndig = FLT_DIG + extra_float_digits;
     324 ECB             : 
     325 GIC       18362 :     if (extra_float_digits > 0)
     326                 :     {
     327 CBC       11992 :         float_to_shortest_decimal_buf(num, ascii);
     328 GBC       11992 :         PG_RETURN_CSTRING(ascii);
     329 ECB             :     }
     330                 : 
     331 GIC        6370 :     (void) pg_strfromd(ascii, 32, ndig, num);
     332            6370 :     PG_RETURN_CSTRING(ascii);
     333                 : }
     334                 : 
     335 ECB             : /*
     336                 :  *      float4recv          - converts external binary format to float4
     337                 :  */
     338                 : Datum
     339 UIC           0 : float4recv(PG_FUNCTION_ARGS)
     340                 : {
     341               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     342                 : 
     343 LBC           0 :     PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));
     344                 : }
     345 ECB             : 
     346                 : /*
     347                 :  *      float4send          - converts float4 to binary format
     348                 :  */
     349                 : Datum
     350 GIC        3246 : float4send(PG_FUNCTION_ARGS)
     351 ECB             : {
     352 CBC        3246 :     float4      num = PG_GETARG_FLOAT4(0);
     353                 :     StringInfoData buf;
     354                 : 
     355            3246 :     pq_begintypsend(&buf);
     356            3246 :     pq_sendfloat4(&buf, num);
     357 GIC        3246 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     358                 : }
     359                 : 
     360                 : /*
     361                 :  *      float8in        - converts "num" to float8
     362                 :  */
     363 EUB             : Datum
     364 GIC      338183 : float8in(PG_FUNCTION_ARGS)
     365 EUB             : {
     366 GIC      338183 :     char       *num = PG_GETARG_CSTRING(0);
     367 EUB             : 
     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
     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
     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 */
     403 GIC      464659 :     while (*num != '\0' && isspace((unsigned char) *num))
     404             650 :         num++;
     405                 : 
     406                 :     /*
     407 ECB             :      * Check for an empty-string input to begin with, to avoid the vagaries of
     408                 :      * strtod() on different platforms.
     409                 :      */
     410 GIC      464009 :     if (*num == '\0')
     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)));
     415 ECB             : 
     416 GIC      464000 :     errno = 0;
     417          464000 :     val = strtod(num, &endptr);
     418                 : 
     419                 :     /* did we not see anything that looks like a double? */
     420          464000 :     if (endptr == num || errno != 0)
     421 ECB             :     {
     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
     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.
     433                 :          */
     434 GIC         132 :         if (pg_strncasecmp(num, "NaN", 3) == 0)
     435                 :         {
     436 UIC           0 :             val = get_float8_nan();
     437               0 :             endptr = num + 3;
     438                 :         }
     439 GIC         132 :         else if (pg_strncasecmp(num, "Infinity", 8) == 0)
     440                 :         {
     441 UIC           0 :             val = get_float8_infinity();
     442               0 :             endptr = num + 8;
     443                 :         }
     444 GIC         132 :         else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
     445 ECB             :         {
     446 UIC           0 :             val = get_float8_infinity();
     447 UBC           0 :             endptr = num + 9;
     448 EUB             :         }
     449 GIC         132 :         else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
     450 ECB             :         {
     451 UIC           0 :             val = -get_float8_infinity();
     452 UBC           0 :             endptr = num + 9;
     453 EUB             :         }
     454 GIC         132 :         else if (pg_strncasecmp(num, "inf", 3) == 0)
     455 ECB             :         {
     456 UIC           0 :             val = get_float8_infinity();
     457 UBC           0 :             endptr = num + 3;
     458 EUB             :         }
     459 GIC         132 :         else if (pg_strncasecmp(num, "+inf", 4) == 0)
     460 ECB             :         {
     461 UIC           0 :             val = get_float8_infinity();
     462 UBC           0 :             endptr = num + 4;
     463 EUB             :         }
     464 GIC         132 :         else if (pg_strncasecmp(num, "-inf", 4) == 0)
     465 ECB             :         {
     466 UIC           0 :             val = -get_float8_infinity();
     467 UBC           0 :             endptr = num + 4;
     468 EUB             :         }
     469 GIC         132 :         else if (save_errno == ERANGE)
     470 ECB             :         {
     471                 :             /*
     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
     475 ECB             :              * detect whether it's a "real" out-of-range condition by checking
     476                 :              * to see if the result is zero or huge.
     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
     480 ECB             :              * that is the current number.
     481                 :              */
     482 GIC          63 :             if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
     483                 :             {
     484              54 :                 char       *errnumber = pstrdup(num);
     485                 : 
     486              54 :                 errnumber[endptr - num] = '\0';
     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                 :             }
     492 ECB             :         }
     493                 :         else
     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 */
     501 GIC      464070 :     while (*endptr != '\0' && isspace((unsigned char) *endptr))
     502 CBC         193 :         endptr++;
     503                 : 
     504                 :     /* report stopping point if wanted, else complain if not end of string */
     505 GIC      463877 :     if (endptr_p)
     506          125727 :         *endptr_p = endptr;
     507          338150 :     else if (*endptr != '\0')
     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)));
     512 ECB             : 
     513 CBC      463856 :     return val;
     514 ECB             : }
     515                 : 
     516                 : 
     517                 : /*
     518                 :  *      float8out       - converts float8 number to a string
     519                 :  *                        using a standard output format
     520                 :  */
     521                 : Datum
     522 GIC      287938 : float8out(PG_FUNCTION_ARGS)
     523                 : {
     524          287938 :     float8      num = PG_GETARG_FLOAT8(0);
     525                 : 
     526          287938 :     PG_RETURN_CSTRING(float8out_internal(num));
     527                 : }
     528                 : 
     529                 : /*
     530                 :  * float8out_internal - guts of float8out()
     531                 :  *
     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 *
     537 CBC     2088200 : float8out_internal(double num)
     538                 : {
     539         2088200 :     char       *ascii = (char *) palloc(32);
     540         2088200 :     int         ndig = DBL_DIG + extra_float_digits;
     541                 : 
     542 GIC     2088200 :     if (extra_float_digits > 0)
     543 ECB             :     {
     544 CBC     1979576 :         double_to_shortest_decimal_buf(num, ascii);
     545 GIC     1979576 :         return ascii;
     546                 :     }
     547                 : 
     548          108624 :     (void) pg_strfromd(ascii, 32, ndig, num);
     549          108624 :     return ascii;
     550                 : }
     551 ECB             : 
     552                 : /*
     553                 :  *      float8recv          - converts external binary format to float8
     554                 :  */
     555                 : Datum
     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                 : }
     562 ECB             : 
     563                 : /*
     564                 :  *      float8send          - converts float8 to binary format
     565                 :  */
     566                 : Datum
     567 CBC        2578 : float8send(PG_FUNCTION_ARGS)
     568 ECB             : {
     569 CBC        2578 :     float8      num = PG_GETARG_FLOAT8(0);
     570                 :     StringInfoData buf;
     571                 : 
     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                 :  */
     586 ECB             : 
     587                 : /*
     588                 :  *      float4abs       - returns |arg1| (absolute value)
     589                 :  */
     590                 : Datum
     591 GIC          15 : float4abs(PG_FUNCTION_ARGS)
     592                 : {
     593              15 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     594                 : 
     595 GNC          15 :     PG_RETURN_FLOAT4(fabsf(arg1));
     596                 : }
     597 ECB             : 
     598                 : /*
     599                 :  *      float4um        - returns -arg1 (unary minus)
     600                 :  */
     601                 : Datum
     602 CBC           8 : float4um(PG_FUNCTION_ARGS)
     603 ECB             : {
     604 GIC           8 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     605                 :     float4      result;
     606                 : 
     607 GBC           8 :     result = -arg1;
     608 GIC           8 :     PG_RETURN_FLOAT4(result);
     609 EUB             : }
     610                 : 
     611                 : Datum
     612 UIC           0 : float4up(PG_FUNCTION_ARGS)
     613                 : {
     614               0 :     float4      arg = PG_GETARG_FLOAT4(0);
     615 ECB             : 
     616 UIC           0 :     PG_RETURN_FLOAT4(arg);
     617 ECB             : }
     618                 : 
     619                 : Datum
     620 GIC           9 : float4larger(PG_FUNCTION_ARGS)
     621 ECB             : {
     622 CBC           9 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     623 GIC           9 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     624 ECB             :     float4      result;
     625                 : 
     626 GIC           9 :     if (float4_gt(arg1, arg2))
     627               3 :         result = arg1;
     628                 :     else
     629 GBC           6 :         result = arg2;
     630 GIC           9 :     PG_RETURN_FLOAT4(result);
     631 EUB             : }
     632                 : 
     633                 : Datum
     634 UIC           0 : float4smaller(PG_FUNCTION_ARGS)
     635 EUB             : {
     636 UBC           0 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     637 UIC           0 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     638 EUB             :     float4      result;
     639                 : 
     640 UIC           0 :     if (float4_lt(arg1, arg2))
     641               0 :         result = arg1;
     642                 :     else
     643               0 :         result = arg2;
     644               0 :     PG_RETURN_FLOAT4(result);
     645                 : }
     646                 : 
     647                 : /*
     648                 :  *      ======================
     649                 :  *      FLOAT8 BASE OPERATIONS
     650                 :  *      ======================
     651                 :  */
     652 ECB             : 
     653                 : /*
     654                 :  *      float8abs       - returns |arg1| (absolute value)
     655                 :  */
     656                 : Datum
     657 GIC       56216 : float8abs(PG_FUNCTION_ARGS)
     658                 : {
     659           56216 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     660                 : 
     661           56216 :     PG_RETURN_FLOAT8(fabs(arg1));
     662                 : }
     663                 : 
     664 ECB             : 
     665                 : /*
     666                 :  *      float8um        - returns -arg1 (unary minus)
     667                 :  */
     668                 : Datum
     669 CBC         161 : float8um(PG_FUNCTION_ARGS)
     670 ECB             : {
     671 GIC         161 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     672                 :     float8      result;
     673                 : 
     674 GBC         161 :     result = -arg1;
     675 GIC         161 :     PG_RETURN_FLOAT8(result);
     676 EUB             : }
     677                 : 
     678                 : Datum
     679 UIC           0 : float8up(PG_FUNCTION_ARGS)
     680                 : {
     681               0 :     float8      arg = PG_GETARG_FLOAT8(0);
     682 ECB             : 
     683 UIC           0 :     PG_RETURN_FLOAT8(arg);
     684 ECB             : }
     685                 : 
     686                 : Datum
     687 GIC        6438 : float8larger(PG_FUNCTION_ARGS)
     688 ECB             : {
     689 CBC        6438 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     690 GIC        6438 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     691 ECB             :     float8      result;
     692                 : 
     693 GIC        6438 :     if (float8_gt(arg1, arg2))
     694            6100 :         result = arg1;
     695                 :     else
     696 CBC         338 :         result = arg2;
     697 GIC        6438 :     PG_RETURN_FLOAT8(result);
     698 ECB             : }
     699                 : 
     700                 : Datum
     701 GIC         576 : float8smaller(PG_FUNCTION_ARGS)
     702 ECB             : {
     703 CBC         576 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     704 GIC         576 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     705 ECB             :     float8      result;
     706                 : 
     707 GIC         576 :     if (float8_lt(arg1, arg2))
     708             444 :         result = arg1;
     709                 :     else
     710             132 :         result = arg2;
     711             576 :     PG_RETURN_FLOAT8(result);
     712                 : }
     713                 : 
     714                 : 
     715                 : /*
     716                 :  *      ====================
     717                 :  *      ARITHMETIC OPERATORS
     718                 :  *      ====================
     719                 :  */
     720                 : 
     721                 : /*
     722                 :  *      float4pl        - returns arg1 + arg2
     723 ECB             :  *      float4mi        - returns arg1 - arg2
     724                 :  *      float4mul       - returns arg1 * arg2
     725                 :  *      float4div       - returns arg1 / arg2
     726                 :  */
     727                 : Datum
     728 CBC          27 : float4pl(PG_FUNCTION_ARGS)
     729                 : {
     730 GIC          27 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     731              27 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     732 ECB             : 
     733 GIC          27 :     PG_RETURN_FLOAT4(float4_pl(arg1, arg2));
     734 ECB             : }
     735                 : 
     736                 : Datum
     737 CBC           9 : float4mi(PG_FUNCTION_ARGS)
     738                 : {
     739 GIC           9 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     740               9 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     741 ECB             : 
     742 GIC           9 :     PG_RETURN_FLOAT4(float4_mi(arg1, arg2));
     743 ECB             : }
     744                 : 
     745                 : Datum
     746 CBC          18 : float4mul(PG_FUNCTION_ARGS)
     747                 : {
     748 GIC          18 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     749              18 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     750 ECB             : 
     751 GIC          18 :     PG_RETURN_FLOAT4(float4_mul(arg1, arg2));
     752 ECB             : }
     753                 : 
     754                 : Datum
     755 CBC          24 : float4div(PG_FUNCTION_ARGS)
     756                 : {
     757 GIC          24 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     758              24 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     759                 : 
     760              24 :     PG_RETURN_FLOAT4(float4_div(arg1, arg2));
     761                 : }
     762                 : 
     763                 : /*
     764                 :  *      float8pl        - returns arg1 + arg2
     765 ECB             :  *      float8mi        - returns arg1 - arg2
     766                 :  *      float8mul       - returns arg1 * arg2
     767                 :  *      float8div       - returns arg1 / arg2
     768                 :  */
     769                 : Datum
     770 CBC       33734 : float8pl(PG_FUNCTION_ARGS)
     771                 : {
     772 GIC       33734 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     773           33734 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     774 ECB             : 
     775 GIC       33734 :     PG_RETURN_FLOAT8(float8_pl(arg1, arg2));
     776 ECB             : }
     777                 : 
     778                 : Datum
     779 CBC        6276 : float8mi(PG_FUNCTION_ARGS)
     780                 : {
     781 GIC        6276 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     782            6276 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     783 ECB             : 
     784 GIC        6276 :     PG_RETURN_FLOAT8(float8_mi(arg1, arg2));
     785 ECB             : }
     786                 : 
     787                 : Datum
     788 CBC      300409 : float8mul(PG_FUNCTION_ARGS)
     789                 : {
     790 GIC      300409 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     791          300409 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     792 ECB             : 
     793 GIC      300409 :     PG_RETURN_FLOAT8(float8_mul(arg1, arg2));
     794 ECB             : }
     795                 : 
     796                 : Datum
     797 CBC        7481 : float8div(PG_FUNCTION_ARGS)
     798                 : {
     799 GIC        7481 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     800            7481 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     801                 : 
     802            7481 :     PG_RETURN_FLOAT8(float8_div(arg1, arg2));
     803                 : }
     804                 : 
     805                 : 
     806                 : /*
     807                 :  *      ====================
     808                 :  *      COMPARISON OPERATORS
     809                 :  *      ====================
     810                 :  */
     811 ECB             : 
     812                 : /*
     813                 :  *      float4{eq,ne,lt,le,gt,ge}       - float4/float4 comparison operations
     814                 :  */
     815                 : int
     816 CBC    25266766 : float4_cmp_internal(float4 a, float4 b)
     817 ECB             : {
     818 GIC    25266766 :     if (float4_gt(a, b))
     819          565349 :         return 1;
     820        24701417 :     if (float4_lt(a, b))
     821 CBC     1225781 :         return -1;
     822 GIC    23475636 :     return 0;
     823 ECB             : }
     824                 : 
     825                 : Datum
     826 CBC       31166 : float4eq(PG_FUNCTION_ARGS)
     827                 : {
     828 GIC       31166 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     829           31166 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     830 ECB             : 
     831 GIC       31166 :     PG_RETURN_BOOL(float4_eq(arg1, arg2));
     832 ECB             : }
     833                 : 
     834                 : Datum
     835 CBC          15 : float4ne(PG_FUNCTION_ARGS)
     836                 : {
     837 GIC          15 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     838              15 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     839 ECB             : 
     840 GIC          15 :     PG_RETURN_BOOL(float4_ne(arg1, arg2));
     841 ECB             : }
     842                 : 
     843                 : Datum
     844 CBC       37005 : float4lt(PG_FUNCTION_ARGS)
     845                 : {
     846 GIC       37005 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     847           37005 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     848 ECB             : 
     849 GIC       37005 :     PG_RETURN_BOOL(float4_lt(arg1, arg2));
     850 ECB             : }
     851                 : 
     852                 : Datum
     853 CBC        1914 : float4le(PG_FUNCTION_ARGS)
     854                 : {
     855 GIC        1914 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     856            1914 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     857 ECB             : 
     858 GIC        1914 :     PG_RETURN_BOOL(float4_le(arg1, arg2));
     859 ECB             : }
     860                 : 
     861                 : Datum
     862 CBC        2319 : float4gt(PG_FUNCTION_ARGS)
     863                 : {
     864 GIC        2319 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     865            2319 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     866 ECB             : 
     867 GIC        2319 :     PG_RETURN_BOOL(float4_gt(arg1, arg2));
     868 ECB             : }
     869                 : 
     870                 : Datum
     871 CBC        1914 : float4ge(PG_FUNCTION_ARGS)
     872                 : {
     873 GIC        1914 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     874            1914 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     875 ECB             : 
     876 GIC        1914 :     PG_RETURN_BOOL(float4_ge(arg1, arg2));
     877 ECB             : }
     878                 : 
     879                 : Datum
     880 CBC      952319 : btfloat4cmp(PG_FUNCTION_ARGS)
     881                 : {
     882 GIC      952319 :     float4      arg1 = PG_GETARG_FLOAT4(0);
     883          952319 :     float4      arg2 = PG_GETARG_FLOAT4(1);
     884 ECB             : 
     885 GIC      952319 :     PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
     886 ECB             : }
     887                 : 
     888                 : static int
     889 CBC    24314447 : btfloat4fastcmp(Datum x, Datum y, SortSupport ssup)
     890                 : {
     891 GIC    24314447 :     float4      arg1 = DatumGetFloat4(x);
     892        24314447 :     float4      arg2 = DatumGetFloat4(y);
     893 ECB             : 
     894 GIC    24314447 :     return float4_cmp_internal(arg1, arg2);
     895 ECB             : }
     896                 : 
     897                 : Datum
     898 CBC        1768 : btfloat4sortsupport(PG_FUNCTION_ARGS)
     899                 : {
     900 GIC        1768 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     901                 : 
     902            1768 :     ssup->comparator = btfloat4fastcmp;
     903            1768 :     PG_RETURN_VOID();
     904                 : }
     905 ECB             : 
     906                 : /*
     907                 :  *      float8{eq,ne,lt,le,gt,ge}       - float8/float8 comparison operations
     908                 :  */
     909                 : int
     910 CBC    12116741 : float8_cmp_internal(float8 a, float8 b)
     911 ECB             : {
     912 GIC    12116741 :     if (float8_gt(a, b))
     913         4432848 :         return 1;
     914         7683893 :     if (float8_lt(a, b))
     915 CBC     7561608 :         return -1;
     916 GIC      122285 :     return 0;
     917 ECB             : }
     918                 : 
     919                 : Datum
     920 CBC      116340 : float8eq(PG_FUNCTION_ARGS)
     921                 : {
     922 GIC      116340 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     923          116340 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     924 ECB             : 
     925 GIC      116340 :     PG_RETURN_BOOL(float8_eq(arg1, arg2));
     926 ECB             : }
     927                 : 
     928                 : Datum
     929 CBC         177 : float8ne(PG_FUNCTION_ARGS)
     930                 : {
     931 GIC         177 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     932             177 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     933 ECB             : 
     934 GIC         177 :     PG_RETURN_BOOL(float8_ne(arg1, arg2));
     935 ECB             : }
     936                 : 
     937                 : Datum
     938 CBC       83790 : float8lt(PG_FUNCTION_ARGS)
     939                 : {
     940 GIC       83790 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     941           83790 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     942 ECB             : 
     943 GIC       83790 :     PG_RETURN_BOOL(float8_lt(arg1, arg2));
     944 ECB             : }
     945                 : 
     946                 : Datum
     947 CBC        3010 : float8le(PG_FUNCTION_ARGS)
     948                 : {
     949 GIC        3010 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     950            3010 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     951 ECB             : 
     952 GIC        3010 :     PG_RETURN_BOOL(float8_le(arg1, arg2));
     953 ECB             : }
     954                 : 
     955                 : Datum
     956 CBC       10033 : float8gt(PG_FUNCTION_ARGS)
     957                 : {
     958 GIC       10033 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     959           10033 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     960 ECB             : 
     961 GIC       10033 :     PG_RETURN_BOOL(float8_gt(arg1, arg2));
     962 ECB             : }
     963                 : 
     964                 : Datum
     965 CBC       10652 : float8ge(PG_FUNCTION_ARGS)
     966                 : {
     967 GIC       10652 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     968           10652 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     969 ECB             : 
     970 GIC       10652 :     PG_RETURN_BOOL(float8_ge(arg1, arg2));
     971 ECB             : }
     972                 : 
     973                 : Datum
     974 CBC        1646 : btfloat8cmp(PG_FUNCTION_ARGS)
     975                 : {
     976 GIC        1646 :     float8      arg1 = PG_GETARG_FLOAT8(0);
     977            1646 :     float8      arg2 = PG_GETARG_FLOAT8(1);
     978 ECB             : 
     979 GIC        1646 :     PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
     980 ECB             : }
     981                 : 
     982                 : static int
     983 CBC     3464685 : btfloat8fastcmp(Datum x, Datum y, SortSupport ssup)
     984                 : {
     985 GIC     3464685 :     float8      arg1 = DatumGetFloat8(x);
     986         3464685 :     float8      arg2 = DatumGetFloat8(y);
     987 ECB             : 
     988 GIC     3464685 :     return float8_cmp_internal(arg1, arg2);
     989 ECB             : }
     990                 : 
     991                 : Datum
     992 CBC         467 : btfloat8sortsupport(PG_FUNCTION_ARGS)
     993                 : {
     994 GIC         467 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     995                 : 
     996 GBC         467 :     ssup->comparator = btfloat8fastcmp;
     997 GIC         467 :     PG_RETURN_VOID();
     998 EUB             : }
     999                 : 
    1000                 : Datum
    1001 UIC           0 : btfloat48cmp(PG_FUNCTION_ARGS)
    1002 EUB             : {
    1003 UIC           0 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    1004               0 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    1005                 : 
    1006 EUB             :     /* widen float4 to float8 and then compare */
    1007 UIC           0 :     PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
    1008 EUB             : }
    1009                 : 
    1010                 : Datum
    1011 UIC           0 : btfloat84cmp(PG_FUNCTION_ARGS)
    1012 EUB             : {
    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.
    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
    1027 CBC         576 : in_range_float8_float8(PG_FUNCTION_ARGS)
    1028 ECB             : {
    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;
    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                 :      */
    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                 : 
    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                 :      */
    1050 CBC         573 :     if (isnan(val))
    1051                 :     {
    1052              93 :         if (isnan(base))
    1053 GIC          30 :             PG_RETURN_BOOL(true);   /* NAN = NAN */
    1054 ECB             :         else
    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
    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                 :      */
    1075 GIC         417 :     if (isinf(offset) && isinf(base) &&
    1076                 :         (sub ? base > 0 : base < 0))
    1077              87 :         PG_RETURN_BOOL(true);
    1078                 : 
    1079                 :     /*
    1080 ECB             :      * Otherwise it should be safe to compute base +/- offset.  We trust the
    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
    1083                 :      * val whether or not that's infinity.
    1084                 :      */
    1085 CBC         330 :     if (sub)
    1086             180 :         sum = base - offset;
    1087                 :     else
    1088             150 :         sum = base + offset;
    1089                 : 
    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.
    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
    1103 CBC         576 : in_range_float4_float8(PG_FUNCTION_ARGS)
    1104 ECB             : {
    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;
    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                 :      */
    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                 : 
    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                 :      */
    1126 CBC         573 :     if (isnan(val))
    1127                 :     {
    1128              93 :         if (isnan(base))
    1129 GIC          30 :             PG_RETURN_BOOL(true);   /* NAN = NAN */
    1130 ECB             :         else
    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
    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                 :      */
    1151 GIC         417 :     if (isinf(offset) && isinf(base) &&
    1152                 :         (sub ? base > 0 : base < 0))
    1153              87 :         PG_RETURN_BOOL(true);
    1154                 : 
    1155                 :     /*
    1156 ECB             :      * Otherwise it should be safe to compute base +/- offset.  We trust the
    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
    1159                 :      * val whether or not that's infinity.
    1160                 :      */
    1161 CBC         330 :     if (sub)
    1162             180 :         sum = base - offset;
    1163                 :     else
    1164             150 :         sum = base + offset;
    1165                 : 
    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                 :  */
    1178 ECB             : 
    1179                 : /*
    1180                 :  *      ftod            - converts a float4 number to a float8 number
    1181                 :  */
    1182                 : Datum
    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                 : 
    1190 ECB             : 
    1191                 : /*
    1192                 :  *      dtof            - converts a float8 number to a float4 number
    1193                 :  */
    1194                 : Datum
    1195 CBC          12 : dtof(PG_FUNCTION_ARGS)
    1196 ECB             : {
    1197 CBC          12 :     float8      num = PG_GETARG_FLOAT8(0);
    1198 ECB             :     float4      result;
    1199                 : 
    1200 GIC          12 :     result = (float4) num;
    1201 GBC          12 :     if (unlikely(isinf(result)) && !isinf(num))
    1202 GIC           6 :         float_overflow_error();
    1203               6 :     if (unlikely(result == 0.0f) && num != 0.0)
    1204               6 :         float_underflow_error();
    1205                 : 
    1206 UIC           0 :     PG_RETURN_FLOAT4(result);
    1207                 : }
    1208                 : 
    1209 ECB             : 
    1210                 : /*
    1211                 :  *      dtoi4           - converts a float8 number to an int4 number
    1212                 :  */
    1213                 : Datum
    1214 GIC      298688 : dtoi4(PG_FUNCTION_ARGS)
    1215                 : {
    1216          298688 :     float8      num = PG_GETARG_FLOAT8(0);
    1217                 : 
    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                 :      */
    1223 GIC      298688 :     num = rint(num);
    1224                 : 
    1225                 :     /* Range check */
    1226 CBC      298688 :     if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT32(num)))
    1227 GIC          12 :         ereport(ERROR,
    1228                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1229                 :                  errmsg("integer out of range")));
    1230                 : 
    1231          298676 :     PG_RETURN_INT32((int32) num);
    1232                 : }
    1233                 : 
    1234 ECB             : 
    1235                 : /*
    1236                 :  *      dtoi2           - converts a float8 number to an int2 number
    1237                 :  */
    1238                 : Datum
    1239 GIC          45 : dtoi2(PG_FUNCTION_ARGS)
    1240                 : {
    1241              45 :     float8      num = PG_GETARG_FLOAT8(0);
    1242                 : 
    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                 :      */
    1248 GIC          45 :     num = rint(num);
    1249                 : 
    1250                 :     /* Range check */
    1251 CBC          45 :     if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT16(num)))
    1252 GIC           6 :         ereport(ERROR,
    1253                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1254                 :                  errmsg("smallint out of range")));
    1255                 : 
    1256              39 :     PG_RETURN_INT16((int16) num);
    1257                 : }
    1258                 : 
    1259 ECB             : 
    1260                 : /*
    1261                 :  *      i4tod           - converts an int4 number to a float8 number
    1262                 :  */
    1263                 : Datum
    1264 GIC     1159549 : i4tod(PG_FUNCTION_ARGS)
    1265                 : {
    1266         1159549 :     int32       num = PG_GETARG_INT32(0);
    1267                 : 
    1268         1159549 :     PG_RETURN_FLOAT8((float8) num);
    1269                 : }
    1270                 : 
    1271 ECB             : 
    1272                 : /*
    1273                 :  *      i2tod           - converts an int2 number to a float8 number
    1274                 :  */
    1275                 : Datum
    1276 GIC         123 : i2tod(PG_FUNCTION_ARGS)
    1277                 : {
    1278             123 :     int16       num = PG_GETARG_INT16(0);
    1279                 : 
    1280             123 :     PG_RETURN_FLOAT8((float8) num);
    1281                 : }
    1282                 : 
    1283 ECB             : 
    1284                 : /*
    1285                 :  *      ftoi4           - converts a float4 number to an int4 number
    1286                 :  */
    1287                 : Datum
    1288 GIC          12 : ftoi4(PG_FUNCTION_ARGS)
    1289                 : {
    1290              12 :     float4      num = PG_GETARG_FLOAT4(0);
    1291                 : 
    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                 :      */
    1297 GIC          12 :     num = rint(num);
    1298                 : 
    1299                 :     /* Range check */
    1300 CBC          12 :     if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT32(num)))
    1301 GIC           6 :         ereport(ERROR,
    1302                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1303                 :                  errmsg("integer out of range")));
    1304                 : 
    1305               6 :     PG_RETURN_INT32((int32) num);
    1306                 : }
    1307                 : 
    1308 ECB             : 
    1309                 : /*
    1310                 :  *      ftoi2           - converts a float4 number to an int2 number
    1311                 :  */
    1312                 : Datum
    1313 GIC          12 : ftoi2(PG_FUNCTION_ARGS)
    1314                 : {
    1315              12 :     float4      num = PG_GETARG_FLOAT4(0);
    1316                 : 
    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                 :      */
    1322 GIC          12 :     num = rint(num);
    1323                 : 
    1324                 :     /* Range check */
    1325 CBC          12 :     if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT16(num)))
    1326 GIC           6 :         ereport(ERROR,
    1327                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1328                 :                  errmsg("smallint out of range")));
    1329                 : 
    1330               6 :     PG_RETURN_INT16((int16) num);
    1331                 : }
    1332                 : 
    1333 ECB             : 
    1334                 : /*
    1335                 :  *      i4tof           - converts an int4 number to a float4 number
    1336                 :  */
    1337                 : Datum
    1338 GIC         232 : i4tof(PG_FUNCTION_ARGS)
    1339                 : {
    1340             232 :     int32       num = PG_GETARG_INT32(0);
    1341                 : 
    1342             232 :     PG_RETURN_FLOAT4((float4) num);
    1343                 : }
    1344                 : 
    1345 EUB             : 
    1346                 : /*
    1347                 :  *      i2tof           - converts an int2 number to a float4 number
    1348                 :  */
    1349                 : Datum
    1350 UIC           0 : i2tof(PG_FUNCTION_ARGS)
    1351                 : {
    1352               0 :     int16       num = PG_GETARG_INT16(0);
    1353                 : 
    1354               0 :     PG_RETURN_FLOAT4((float4) num);
    1355                 : }
    1356                 : 
    1357                 : 
    1358                 : /*
    1359                 :  *      =======================
    1360                 :  *      RANDOM FLOAT8 OPERATORS
    1361                 :  *      =======================
    1362                 :  */
    1363 ECB             : 
    1364                 : /*
    1365                 :  *      dround          - returns   ROUND(arg1)
    1366                 :  */
    1367                 : Datum
    1368 GIC        9768 : dround(PG_FUNCTION_ARGS)
    1369                 : {
    1370            9768 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1371                 : 
    1372            9768 :     PG_RETURN_FLOAT8(rint(arg1));
    1373                 : }
    1374                 : 
    1375 ECB             : /*
    1376                 :  *      dceil           - returns the smallest integer greater than or
    1377                 :  *                        equal to the specified float
    1378                 :  */
    1379                 : Datum
    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                 : 
    1387 ECB             : /*
    1388                 :  *      dfloor          - returns the largest integer lesser than or
    1389                 :  *                        equal to the specified float
    1390                 :  */
    1391                 : Datum
    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                 : /*
    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
    1405 CBC          15 : dsign(PG_FUNCTION_ARGS)
    1406 ECB             : {
    1407 CBC          15 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1408 ECB             :     float8      result;
    1409                 : 
    1410 CBC          15 :     if (arg1 > 0)
    1411 GIC           9 :         result = 1.0;
    1412 CBC           6 :     else if (arg1 < 0)
    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
    1423 ECB             :  *                                      than or equal to arg1
    1424                 :  *                        arg1 < 0   ... the least integer greater
    1425                 :  *                                      than or equal to arg1
    1426                 :  */
    1427                 : Datum
    1428 CBC          15 : dtrunc(PG_FUNCTION_ARGS)
    1429 ECB             : {
    1430 GIC          15 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1431 ECB             :     float8      result;
    1432                 : 
    1433 CBC          15 :     if (arg1 >= 0)
    1434 GIC          12 :         result = floor(arg1);
    1435                 :     else
    1436               3 :         result = -floor(-arg1);
    1437                 : 
    1438              15 :     PG_RETURN_FLOAT8(result);
    1439                 : }
    1440                 : 
    1441 ECB             : 
    1442                 : /*
    1443                 :  *      dsqrt           - returns square root of arg1
    1444                 :  */
    1445                 : Datum
    1446 CBC        2024 : dsqrt(PG_FUNCTION_ARGS)
    1447 EUB             : {
    1448 GIC        2024 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1449                 :     float8      result;
    1450                 : 
    1451 CBC        2024 :     if (arg1 < 0)
    1452 LBC           0 :         ereport(ERROR,
    1453 EUB             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    1454 ECB             :                  errmsg("cannot take square root of a negative number")));
    1455 EUB             : 
    1456 GIC        2024 :     result = sqrt(arg1);
    1457 CBC        2024 :     if (unlikely(isinf(result)) && !isinf(arg1))
    1458 UIC           0 :         float_overflow_error();
    1459 GIC        2024 :     if (unlikely(result == 0.0) && arg1 != 0.0)
    1460 UIC           0 :         float_underflow_error();
    1461                 : 
    1462 GIC        2024 :     PG_RETURN_FLOAT8(result);
    1463                 : }
    1464                 : 
    1465 ECB             : 
    1466                 : /*
    1467                 :  *      dcbrt           - returns cube root of arg1
    1468                 :  */
    1469                 : Datum
    1470 CBC          18 : dcbrt(PG_FUNCTION_ARGS)
    1471 ECB             : {
    1472 GBC          18 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1473 ECB             :     float8      result;
    1474 EUB             : 
    1475 GIC          18 :     result = cbrt(arg1);
    1476 CBC          18 :     if (unlikely(isinf(result)) && !isinf(arg1))
    1477 UIC           0 :         float_overflow_error();
    1478 GIC          18 :     if (unlikely(result == 0.0) && arg1 != 0.0)
    1479 UIC           0 :         float_underflow_error();
    1480                 : 
    1481 GIC          18 :     PG_RETURN_FLOAT8(result);
    1482                 : }
    1483                 : 
    1484 ECB             : 
    1485                 : /*
    1486                 :  *      dpow            - returns pow(arg1,arg2)
    1487                 :  */
    1488                 : Datum
    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                 :     /*
    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                 :      */
    1501 GIC         334 :     if (isnan(arg1))
    1502 ECB             :     {
    1503 GIC           9 :         if (isnan(arg2) || arg2 != 0.0)
    1504 CBC           6 :             PG_RETURN_FLOAT8(get_float8_nan());
    1505               3 :         PG_RETURN_FLOAT8(1.0);
    1506 ECB             :     }
    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                 : 
    1514 ECB             :     /*
    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.
    1518                 :      */
    1519 CBC         316 :     if (arg1 == 0 && arg2 < 0)
    1520 GIC           3 :         ereport(ERROR,
    1521                 :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    1522                 :                  errmsg("zero raised to a negative power is undefined")));
    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                 : 
    1528 ECB             :     /*
    1529                 :      * We don't trust the platform's pow() to handle infinity cases per POSIX
    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.
    1532                 :      */
    1533 CBC         310 :     if (isinf(arg2))
    1534 ECB             :     {
    1535 GIC          51 :         float8      absx = fabs(arg1);
    1536 ECB             : 
    1537 CBC          51 :         if (absx == 1.0)
    1538 GIC          12 :             result = 1.0;
    1539 CBC          39 :         else if (arg2 > 0.0) /* y = +Inf */
    1540                 :         {
    1541 GIC          21 :             if (absx > 1.0)
    1542              12 :                 result = arg2;
    1543 ECB             :             else
    1544 CBC           9 :                 result = 0.0;
    1545                 :         }
    1546 ECB             :         else                    /* y = -Inf */
    1547                 :         {
    1548 GIC          18 :             if (absx > 1.0)
    1549 CBC          12 :                 result = 0.0;
    1550                 :             else
    1551               6 :                 result = -arg2;
    1552 ECB             :         }
    1553                 :     }
    1554 GIC         259 :     else if (isinf(arg1))
    1555 ECB             :     {
    1556 CBC          24 :         if (arg2 == 0.0)
    1557 GIC           6 :             result = 1.0;
    1558 CBC          18 :         else if (arg1 > 0.0) /* x = +Inf */
    1559                 :         {
    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                 :             /*
    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                 :              */
    1573 GIC          12 :             float8      halfy = arg2 / 2;   /* should be computed exactly */
    1574 CBC          12 :             bool        yisoddinteger = (floor(halfy) != halfy);
    1575                 : 
    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
    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                 :          */
    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
    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                 :              */
    1606 UIC           0 :             if (arg1 == 0.0)
    1607 UBC           0 :                 result = 0.0;   /* we already verified y is positive */
    1608 EUB             :             else
    1609                 :             {
    1610 UBC           0 :                 float8      absx = fabs(arg1);
    1611                 : 
    1612               0 :                 if (absx == 1.0)
    1613 UIC           0 :                     result = 1.0;
    1614               0 :                 else if (arg2 >= 0.0 ? (absx > 1.0) : (absx < 1.0))
    1615 LBC           0 :                     float_overflow_error();
    1616                 :                 else
    1617               0 :                     float_underflow_error();
    1618 ECB             :             }
    1619                 :         }
    1620 GBC         235 :         else if (errno == ERANGE)
    1621                 :         {
    1622 GIC           3 :             if (result != 0.0)
    1623               3 :                 float_overflow_error();
    1624 ECB             :             else
    1625 UBC           0 :                 float_underflow_error();
    1626 ECB             :         }
    1627 EUB             :         else
    1628                 :         {
    1629 GIC         232 :             if (unlikely(isinf(result)))
    1630 UIC           0 :                 float_overflow_error();
    1631 CBC         232 :             if (unlikely(result == 0.0) && arg1 != 0.0)
    1632 UIC           0 :                 float_underflow_error();
    1633                 :         }
    1634                 :     }
    1635                 : 
    1636 GIC         307 :     PG_RETURN_FLOAT8(result);
    1637                 : }
    1638                 : 
    1639 ECB             : 
    1640                 : /*
    1641                 :  *      dexp            - returns the exponential function of arg1
    1642                 :  */
    1643                 : Datum
    1644 GIC          27 : dexp(PG_FUNCTION_ARGS)
    1645                 : {
    1646              27 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1647                 :     float8      result;
    1648                 : 
    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                 :      */
    1654 CBC          27 :     if (isnan(arg1))
    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
    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                 :          */
    1667 GBC          18 :         errno = 0;
    1668 GIC          18 :         result = exp(arg1);
    1669 CBC          18 :         if (unlikely(errno == ERANGE))
    1670                 :         {
    1671               3 :             if (result != 0.0)
    1672 UBC           0 :                 float_overflow_error();
    1673 ECB             :             else
    1674 GBC           3 :                 float_underflow_error();
    1675                 :         }
    1676 GIC          15 :         else if (unlikely(isinf(result)))
    1677 LBC           0 :             float_overflow_error();
    1678 GIC          15 :         else if (unlikely(result == 0.0))
    1679 UIC           0 :             float_underflow_error();
    1680                 :     }
    1681                 : 
    1682 GIC          24 :     PG_RETURN_FLOAT8(result);
    1683                 : }
    1684                 : 
    1685 ECB             : 
    1686                 : /*
    1687                 :  *      dlog1           - returns the natural logarithm of arg1
    1688                 :  */
    1689                 : Datum
    1690 GIC          15 : dlog1(PG_FUNCTION_ARGS)
    1691                 : {
    1692              15 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1693                 :     float8      result;
    1694 ECB             : 
    1695                 :     /*
    1696                 :      * Emit particular SQLSTATE error codes for ln(). This is required by the
    1697                 :      * SQL standard.
    1698                 :      */
    1699 CBC          15 :     if (arg1 == 0.0)
    1700 GIC           3 :         ereport(ERROR,
    1701                 :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    1702                 :                  errmsg("cannot take logarithm of zero")));
    1703 CBC          12 :     if (arg1 < 0)
    1704               3 :         ereport(ERROR,
    1705 EUB             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    1706 ECB             :                  errmsg("cannot take logarithm of a negative number")));
    1707 EUB             : 
    1708 GIC           9 :     result = log(arg1);
    1709 CBC           9 :     if (unlikely(isinf(result)) && !isinf(arg1))
    1710 UIC           0 :         float_overflow_error();
    1711 GIC           9 :     if (unlikely(result == 0.0) && arg1 != 1.0)
    1712 UIC           0 :         float_underflow_error();
    1713                 : 
    1714 GIC           9 :     PG_RETURN_FLOAT8(result);
    1715                 : }
    1716                 : 
    1717 EUB             : 
    1718                 : /*
    1719                 :  *      dlog10          - returns the base 10 logarithm of arg1
    1720                 :  */
    1721                 : Datum
    1722 UIC           0 : dlog10(PG_FUNCTION_ARGS)
    1723                 : {
    1724               0 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1725                 :     float8      result;
    1726                 : 
    1727 EUB             :     /*
    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.
    1731                 :      */
    1732 UBC           0 :     if (arg1 == 0.0)
    1733 UIC           0 :         ereport(ERROR,
    1734                 :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    1735                 :                  errmsg("cannot take logarithm of zero")));
    1736 UBC           0 :     if (arg1 < 0)
    1737               0 :         ereport(ERROR,
    1738 EUB             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    1739                 :                  errmsg("cannot take logarithm of a negative number")));
    1740                 : 
    1741 UIC           0 :     result = log10(arg1);
    1742 UBC           0 :     if (unlikely(isinf(result)) && !isinf(arg1))
    1743 UIC           0 :         float_overflow_error();
    1744               0 :     if (unlikely(result == 0.0) && arg1 != 1.0)
    1745               0 :         float_underflow_error();
    1746                 : 
    1747               0 :     PG_RETURN_FLOAT8(result);
    1748                 : }
    1749                 : 
    1750 EUB             : 
    1751                 : /*
    1752                 :  *      dacos           - returns the arccos of arg1 (radians)
    1753                 :  */
    1754                 : Datum
    1755 UIC           0 : dacos(PG_FUNCTION_ARGS)
    1756 EUB             : {
    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 */
    1761 UIC           0 :     if (isnan(arg1))
    1762               0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1763                 : 
    1764 EUB             :     /*
    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                 :      */
    1769 UBC           0 :     if (arg1 < -1.0 || arg1 > 1.0)
    1770               0 :         ereport(ERROR,
    1771 EUB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1772                 :                  errmsg("input is out of range")));
    1773                 : 
    1774 UIC           0 :     result = acos(arg1);
    1775               0 :     if (unlikely(isinf(result)))
    1776               0 :         float_overflow_error();
    1777                 : 
    1778               0 :     PG_RETURN_FLOAT8(result);
    1779                 : }
    1780                 : 
    1781 ECB             : 
    1782                 : /*
    1783                 :  *      dasin           - returns the arcsin of arg1 (radians)
    1784                 :  */
    1785                 : Datum
    1786 GIC          55 : dasin(PG_FUNCTION_ARGS)
    1787 ECB             : {
    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 */
    1792 GIC          55 :     if (isnan(arg1))
    1793 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1794                 : 
    1795 ECB             :     /*
    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                 :      */
    1800 CBC          55 :     if (arg1 < -1.0 || arg1 > 1.0)
    1801 LBC           0 :         ereport(ERROR,
    1802 EUB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1803                 :                  errmsg("input is out of range")));
    1804 ECB             : 
    1805 GIC          55 :     result = asin(arg1);
    1806              55 :     if (unlikely(isinf(result)))
    1807 UIC           0 :         float_overflow_error();
    1808                 : 
    1809 GIC          55 :     PG_RETURN_FLOAT8(result);
    1810                 : }
    1811                 : 
    1812 EUB             : 
    1813                 : /*
    1814                 :  *      datan           - returns the arctan of arg1 (radians)
    1815                 :  */
    1816                 : Datum
    1817 UIC           0 : datan(PG_FUNCTION_ARGS)
    1818 EUB             : {
    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 */
    1823 UIC           0 :     if (isnan(arg1))
    1824               0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1825                 : 
    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                 :      */
    1831 UIC           0 :     result = atan(arg1);
    1832               0 :     if (unlikely(isinf(result)))
    1833               0 :         float_overflow_error();
    1834                 : 
    1835               0 :     PG_RETURN_FLOAT8(result);
    1836                 : }
    1837                 : 
    1838 ECB             : 
    1839                 : /*
    1840                 :  *      atan2           - returns the arctan of arg1/arg2 (radians)
    1841                 :  */
    1842                 : Datum
    1843 GIC          20 : datan2(PG_FUNCTION_ARGS)
    1844                 : {
    1845 CBC          20 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    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 */
    1850 GIC          20 :     if (isnan(arg1) || isnan(arg2))
    1851 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1852 ECB             : 
    1853                 :     /*
    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.
    1856 ECB             :      */
    1857 GIC          20 :     result = atan2(arg1, arg2);
    1858              20 :     if (unlikely(isinf(result)))
    1859 UIC           0 :         float_overflow_error();
    1860                 : 
    1861 GIC          20 :     PG_RETURN_FLOAT8(result);
    1862                 : }
    1863                 : 
    1864 ECB             : 
    1865                 : /*
    1866                 :  *      dcos            - returns the cosine of arg1 (radians)
    1867                 :  */
    1868                 : Datum
    1869 GIC         585 : dcos(PG_FUNCTION_ARGS)
    1870 ECB             : {
    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 */
    1875 GIC         585 :     if (isnan(arg1))
    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                 :      *
    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
    1891 EUB             :      * inputs.
    1892                 :      */
    1893 GIC         585 :     errno = 0;
    1894 CBC         585 :     result = cos(arg1);
    1895 GBC         585 :     if (errno != 0 || isinf(arg1))
    1896 UIC           0 :         ereport(ERROR,
    1897 ECB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1898                 :                  errmsg("input is out of range")));
    1899 GIC         585 :     if (unlikely(isinf(result)))
    1900 UIC           0 :         float_overflow_error();
    1901                 : 
    1902 GIC         585 :     PG_RETURN_FLOAT8(result);
    1903                 : }
    1904                 : 
    1905 EUB             : 
    1906                 : /*
    1907                 :  *      dcot            - returns the cotangent of arg1 (radians)
    1908                 :  */
    1909                 : Datum
    1910 UIC           0 : dcot(PG_FUNCTION_ARGS)
    1911 EUB             : {
    1912 UBC           0 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1913                 :     float8      result;
    1914                 : 
    1915 EUB             :     /* Per the POSIX spec, return NaN if the input is NaN */
    1916 UBC           0 :     if (isnan(arg1))
    1917               0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1918 EUB             : 
    1919                 :     /* Be sure to throw an error if the input is infinite --- see dcos() */
    1920 UIC           0 :     errno = 0;
    1921               0 :     result = tan(arg1);
    1922 UBC           0 :     if (errno != 0 || isinf(arg1))
    1923 UIC           0 :         ereport(ERROR,
    1924                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1925 EUB             :                  errmsg("input is out of range")));
    1926                 : 
    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                 : 
    1933 ECB             : 
    1934                 : /*
    1935                 :  *      dsin            - returns the sine of arg1 (radians)
    1936                 :  */
    1937                 : Datum
    1938 GIC         469 : dsin(PG_FUNCTION_ARGS)
    1939 ECB             : {
    1940 GBC         469 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1941                 :     float8      result;
    1942                 : 
    1943 ECB             :     /* Per the POSIX spec, return NaN if the input is NaN */
    1944 CBC         469 :     if (isnan(arg1))
    1945 LBC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1946 EUB             : 
    1947                 :     /* Be sure to throw an error if the input is infinite --- see dcos() */
    1948 GIC         469 :     errno = 0;
    1949 CBC         469 :     result = sin(arg1);
    1950 GBC         469 :     if (errno != 0 || isinf(arg1))
    1951 UIC           0 :         ereport(ERROR,
    1952 ECB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1953                 :                  errmsg("input is out of range")));
    1954 GIC         469 :     if (unlikely(isinf(result)))
    1955 UIC           0 :         float_overflow_error();
    1956                 : 
    1957 GIC         469 :     PG_RETURN_FLOAT8(result);
    1958                 : }
    1959                 : 
    1960 EUB             : 
    1961                 : /*
    1962                 :  *      dtan            - returns the tangent of arg1 (radians)
    1963                 :  */
    1964                 : Datum
    1965 UIC           0 : dtan(PG_FUNCTION_ARGS)
    1966 EUB             : {
    1967 UBC           0 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    1968                 :     float8      result;
    1969                 : 
    1970 EUB             :     /* Per the POSIX spec, return NaN if the input is NaN */
    1971 UBC           0 :     if (isnan(arg1))
    1972               0 :         PG_RETURN_FLOAT8(get_float8_nan());
    1973 EUB             : 
    1974                 :     /* Be sure to throw an error if the input is infinite --- see dcos() */
    1975 UIC           0 :     errno = 0;
    1976               0 :     result = tan(arg1);
    1977               0 :     if (errno != 0 || isinf(arg1))
    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                 : 
    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.
    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.)
    2017                 :  */
    2018                 : static void
    2019 CBC           3 : init_degree_constants(void)
    2020 ECB             : {
    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);
    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);
    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                 :  *
    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
    2048 GIC          42 : asind_q1(double x)
    2049                 : {
    2050                 :     /*
    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                 :      */
    2056 GIC          42 :     if (x <= 0.5)
    2057                 :     {
    2058              24 :         volatile float8 asin_x = asin(x);
    2059 ECB             : 
    2060 GIC          24 :         return (asin_x / asin_0_5) * 30.0;
    2061 ECB             :     }
    2062                 :     else
    2063                 :     {
    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                 :  *
    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
    2081 GIC          18 : acosd_q1(double x)
    2082                 : {
    2083                 :     /*
    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                 :      */
    2089 GIC          18 :     if (x <= 0.5)
    2090                 :     {
    2091              12 :         volatile float8 asin_x = asin(x);
    2092 ECB             : 
    2093 GIC          12 :         return 90.0 - (asin_x / asin_0_5) * 30.0;
    2094 ECB             :     }
    2095                 :     else
    2096                 :     {
    2097 GIC           6 :         volatile float8 acos_x = acos(x);
    2098                 : 
    2099               6 :         return (acos_x / acos_0_5) * 60.0;
    2100                 :     }
    2101                 : }
    2102                 : 
    2103 ECB             : 
    2104                 : /*
    2105                 :  *      dacosd          - returns the arccos of arg1 (degrees)
    2106                 :  */
    2107                 : Datum
    2108 GIC          30 : dacosd(PG_FUNCTION_ARGS)
    2109 ECB             : {
    2110 GBC          30 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2111                 :     float8      result;
    2112 ECB             : 
    2113                 :     /* Per the POSIX spec, return NaN if the input is NaN */
    2114 GIC          30 :     if (isnan(arg1))
    2115 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2116                 : 
    2117 GIC          30 :     INIT_DEGREE_CONSTANTS();
    2118                 : 
    2119 ECB             :     /*
    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                 :      */
    2124 CBC          30 :     if (arg1 < -1.0 || arg1 > 1.0)
    2125 LBC           0 :         ereport(ERROR,
    2126                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2127 ECB             :                  errmsg("input is out of range")));
    2128                 : 
    2129 CBC          30 :     if (arg1 >= 0.0)
    2130 GBC          18 :         result = acosd_q1(arg1);
    2131                 :     else
    2132 CBC          12 :         result = 90.0 + asind_q1(-arg1);
    2133                 : 
    2134 GIC          30 :     if (unlikely(isinf(result)))
    2135 UIC           0 :         float_overflow_error();
    2136                 : 
    2137 GIC          30 :     PG_RETURN_FLOAT8(result);
    2138                 : }
    2139                 : 
    2140 ECB             : 
    2141                 : /*
    2142                 :  *      dasind          - returns the arcsin of arg1 (degrees)
    2143                 :  */
    2144                 : Datum
    2145 GIC          30 : dasind(PG_FUNCTION_ARGS)
    2146 ECB             : {
    2147 GBC          30 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2148                 :     float8      result;
    2149 ECB             : 
    2150                 :     /* Per the POSIX spec, return NaN if the input is NaN */
    2151 GIC          30 :     if (isnan(arg1))
    2152 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2153                 : 
    2154 GIC          30 :     INIT_DEGREE_CONSTANTS();
    2155                 : 
    2156 ECB             :     /*
    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                 :      */
    2161 CBC          30 :     if (arg1 < -1.0 || arg1 > 1.0)
    2162 LBC           0 :         ereport(ERROR,
    2163                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2164 ECB             :                  errmsg("input is out of range")));
    2165                 : 
    2166 CBC          30 :     if (arg1 >= 0.0)
    2167 GBC          18 :         result = asind_q1(arg1);
    2168                 :     else
    2169 CBC          12 :         result = -asind_q1(-arg1);
    2170                 : 
    2171 GIC          30 :     if (unlikely(isinf(result)))
    2172 UIC           0 :         float_overflow_error();
    2173                 : 
    2174 GIC          30 :     PG_RETURN_FLOAT8(result);
    2175                 : }
    2176                 : 
    2177 ECB             : 
    2178                 : /*
    2179                 :  *      datand          - returns the arctan of arg1 (degrees)
    2180                 :  */
    2181                 : Datum
    2182 GIC          30 : datand(PG_FUNCTION_ARGS)
    2183                 : {
    2184 CBC          30 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2185 EUB             :     float8      result;
    2186                 :     volatile float8 atan_arg1;
    2187 ECB             : 
    2188                 :     /* Per the POSIX spec, return NaN if the input is NaN */
    2189 GIC          30 :     if (isnan(arg1))
    2190 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2191                 : 
    2192 GIC          30 :     INIT_DEGREE_CONSTANTS();
    2193                 : 
    2194                 :     /*
    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.
    2199 EUB             :      */
    2200 GIC          30 :     atan_arg1 = atan(arg1);
    2201 CBC          30 :     result = (atan_arg1 / atan_1_0) * 45.0;
    2202                 : 
    2203 GIC          30 :     if (unlikely(isinf(result)))
    2204 UIC           0 :         float_overflow_error();
    2205                 : 
    2206 GIC          30 :     PG_RETURN_FLOAT8(result);
    2207                 : }
    2208                 : 
    2209 ECB             : 
    2210                 : /*
    2211                 :  *      atan2d          - returns the arctan of arg1/arg2 (degrees)
    2212                 :  */
    2213                 : Datum
    2214 GIC          30 : datan2d(PG_FUNCTION_ARGS)
    2215                 : {
    2216              30 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2217 CBC          30 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    2218 EUB             :     float8      result;
    2219                 :     volatile float8 atan2_arg1_arg2;
    2220 ECB             : 
    2221                 :     /* Per the POSIX spec, return NaN if either input is NaN */
    2222 GIC          30 :     if (isnan(arg1) || isnan(arg2))
    2223 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2224                 : 
    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                 :      *
    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.
    2235 EUB             :      */
    2236 GIC          30 :     atan2_arg1_arg2 = atan2(arg1, arg2);
    2237 CBC          30 :     result = (atan2_arg1_arg2 / atan_1_0) * 45.0;
    2238                 : 
    2239 GIC          30 :     if (unlikely(isinf(result)))
    2240 UIC           0 :         float_overflow_error();
    2241                 : 
    2242 GIC          30 :     PG_RETURN_FLOAT8(result);
    2243                 : }
    2244                 : 
    2245                 : 
    2246                 : /*
    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
    2252 GIC         159 : sind_0_to_30(double x)
    2253                 : {
    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                 : /*
    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
    2266 GIC         267 : cosd_0_to_60(double x)
    2267                 : {
    2268             267 :     volatile float8 one_minus_cos_x = 1.0 - cos(x * RADIANS_PER_DEGREE);
    2269                 : 
    2270             267 :     return 1.0 - (one_minus_cos_x / one_minus_cos_60) / 2.0;
    2271                 : }
    2272                 : 
    2273                 : 
    2274 ECB             : /*
    2275                 :  *      sind_q1         - returns the sine of an angle in the first quadrant
    2276                 :  *                        (0 to 90 degrees).
    2277                 :  */
    2278                 : static double
    2279 GIC         213 : sind_q1(double x)
    2280                 : {
    2281                 :     /*
    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                 :      */
    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                 : 
    2294 ECB             : /*
    2295                 :  *      cosd_q1         - returns the cosine of an angle in the first quadrant
    2296                 :  *                        (0 to 90 degrees).
    2297                 :  */
    2298                 : static double
    2299 GIC         213 : cosd_q1(double x)
    2300                 : {
    2301                 :     /*
    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                 :      */
    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                 : 
    2313 ECB             : 
    2314                 : /*
    2315                 :  *      dcosd           - returns the cosine of arg1 (degrees)
    2316                 :  */
    2317                 : Datum
    2318 GIC          99 : dcosd(PG_FUNCTION_ARGS)
    2319                 : {
    2320              99 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2321                 :     float8      result;
    2322              99 :     int         sign = 1;
    2323 ECB             : 
    2324 EUB             :     /*
    2325                 :      * Per the POSIX spec, return NaN if the input is NaN and throw an error
    2326 ECB             :      * if the input is infinite.
    2327 EUB             :      */
    2328 GIC          99 :     if (isnan(arg1))
    2329 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2330                 : 
    2331 CBC          99 :     if (isinf(arg1))
    2332 UIC           0 :         ereport(ERROR,
    2333                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2334 ECB             :                  errmsg("input is out of range")));
    2335                 : 
    2336 CBC          99 :     INIT_DEGREE_CONSTANTS();
    2337                 : 
    2338                 :     /* Reduce the range of the input to [0,90] degrees */
    2339 GBC          99 :     arg1 = fmod(arg1, 360.0);
    2340                 : 
    2341 GIC          99 :     if (arg1 < 0.0)
    2342 ECB             :     {
    2343                 :         /* cosd(-x) = cosd(x) */
    2344 UIC           0 :         arg1 = -arg1;
    2345 ECB             :     }
    2346                 : 
    2347 GIC          99 :     if (arg1 > 180.0)
    2348 ECB             :     {
    2349                 :         /* cosd(360-x) = cosd(x) */
    2350 GIC          27 :         arg1 = 360.0 - arg1;
    2351 ECB             :     }
    2352                 : 
    2353 GIC          99 :     if (arg1 > 90.0)
    2354                 :     {
    2355 ECB             :         /* cosd(180-x) = -cosd(x) */
    2356 GIC          27 :         arg1 = 180.0 - arg1;
    2357 CBC          27 :         sign = -sign;
    2358 EUB             :     }
    2359                 : 
    2360 CBC          99 :     result = sign * cosd_q1(arg1);
    2361                 : 
    2362 GIC          99 :     if (unlikely(isinf(result)))
    2363 UIC           0 :         float_overflow_error();
    2364                 : 
    2365 GIC          99 :     PG_RETURN_FLOAT8(result);
    2366                 : }
    2367                 : 
    2368 ECB             : 
    2369                 : /*
    2370                 :  *      dcotd           - returns the cotangent of arg1 (degrees)
    2371                 :  */
    2372                 : Datum
    2373 CBC          54 : dcotd(PG_FUNCTION_ARGS)
    2374                 : {
    2375 GIC          54 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2376                 :     float8      result;
    2377                 :     volatile float8 cot_arg1;
    2378              54 :     int         sign = 1;
    2379 ECB             : 
    2380 EUB             :     /*
    2381                 :      * Per the POSIX spec, return NaN if the input is NaN and throw an error
    2382 ECB             :      * if the input is infinite.
    2383 EUB             :      */
    2384 GIC          54 :     if (isnan(arg1))
    2385 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2386                 : 
    2387 CBC          54 :     if (isinf(arg1))
    2388 UIC           0 :         ereport(ERROR,
    2389                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2390 ECB             :                  errmsg("input is out of range")));
    2391                 : 
    2392 CBC          54 :     INIT_DEGREE_CONSTANTS();
    2393                 : 
    2394                 :     /* Reduce the range of the input to [0,90] degrees */
    2395 GBC          54 :     arg1 = fmod(arg1, 360.0);
    2396 EUB             : 
    2397 GIC          54 :     if (arg1 < 0.0)
    2398                 :     {
    2399 ECB             :         /* cotd(-x) = -cotd(x) */
    2400 UIC           0 :         arg1 = -arg1;
    2401               0 :         sign = -sign;
    2402 ECB             :     }
    2403                 : 
    2404 GIC          54 :     if (arg1 > 180.0)
    2405                 :     {
    2406 ECB             :         /* cotd(360-x) = -cotd(x) */
    2407 GIC          18 :         arg1 = 360.0 - arg1;
    2408              18 :         sign = -sign;
    2409 ECB             :     }
    2410                 : 
    2411 GIC          54 :     if (arg1 > 90.0)
    2412                 :     {
    2413 ECB             :         /* cotd(180-x) = -cotd(x) */
    2414 CBC          18 :         arg1 = 180.0 - arg1;
    2415 GIC          18 :         sign = -sign;
    2416                 :     }
    2417                 : 
    2418              54 :     cot_arg1 = cosd_q1(arg1) / sind_q1(arg1);
    2419              54 :     result = sign * (cot_arg1 / cot_45);
    2420                 : 
    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                 :      */
    2426 CBC          54 :     if (result == 0.0)
    2427 GIC          12 :         result = 0.0;
    2428                 : 
    2429                 :     /* Not checking for overflow because cotd(0) == Inf */
    2430                 : 
    2431              54 :     PG_RETURN_FLOAT8(result);
    2432                 : }
    2433                 : 
    2434 ECB             : 
    2435                 : /*
    2436                 :  *      dsind           - returns the sine of arg1 (degrees)
    2437                 :  */
    2438                 : Datum
    2439 GIC          99 : dsind(PG_FUNCTION_ARGS)
    2440                 : {
    2441              99 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2442                 :     float8      result;
    2443              99 :     int         sign = 1;
    2444 ECB             : 
    2445 EUB             :     /*
    2446                 :      * Per the POSIX spec, return NaN if the input is NaN and throw an error
    2447 ECB             :      * if the input is infinite.
    2448 EUB             :      */
    2449 GIC          99 :     if (isnan(arg1))
    2450 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2451                 : 
    2452 CBC          99 :     if (isinf(arg1))
    2453 UIC           0 :         ereport(ERROR,
    2454                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2455 ECB             :                  errmsg("input is out of range")));
    2456                 : 
    2457 CBC          99 :     INIT_DEGREE_CONSTANTS();
    2458                 : 
    2459                 :     /* Reduce the range of the input to [0,90] degrees */
    2460 GBC          99 :     arg1 = fmod(arg1, 360.0);
    2461 EUB             : 
    2462 GIC          99 :     if (arg1 < 0.0)
    2463                 :     {
    2464 ECB             :         /* sind(-x) = -sind(x) */
    2465 UIC           0 :         arg1 = -arg1;
    2466               0 :         sign = -sign;
    2467 ECB             :     }
    2468                 : 
    2469 GIC          99 :     if (arg1 > 180.0)
    2470                 :     {
    2471 ECB             :         /* sind(360-x) = -sind(x) */
    2472 GIC          27 :         arg1 = 360.0 - arg1;
    2473              27 :         sign = -sign;
    2474 ECB             :     }
    2475                 : 
    2476 GIC          99 :     if (arg1 > 90.0)
    2477 ECB             :     {
    2478                 :         /* sind(180-x) = sind(x) */
    2479 CBC          27 :         arg1 = 180.0 - arg1;
    2480 EUB             :     }
    2481                 : 
    2482 CBC          99 :     result = sign * sind_q1(arg1);
    2483                 : 
    2484 GIC          99 :     if (unlikely(isinf(result)))
    2485 UIC           0 :         float_overflow_error();
    2486                 : 
    2487 GIC          99 :     PG_RETURN_FLOAT8(result);
    2488                 : }
    2489                 : 
    2490 ECB             : 
    2491                 : /*
    2492                 :  *      dtand           - returns the tangent of arg1 (degrees)
    2493                 :  */
    2494                 : Datum
    2495 CBC          54 : dtand(PG_FUNCTION_ARGS)
    2496                 : {
    2497 GIC          54 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2498                 :     float8      result;
    2499                 :     volatile float8 tan_arg1;
    2500              54 :     int         sign = 1;
    2501 ECB             : 
    2502 EUB             :     /*
    2503                 :      * Per the POSIX spec, return NaN if the input is NaN and throw an error
    2504 ECB             :      * if the input is infinite.
    2505 EUB             :      */
    2506 GIC          54 :     if (isnan(arg1))
    2507 UIC           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    2508                 : 
    2509 CBC          54 :     if (isinf(arg1))
    2510 UIC           0 :         ereport(ERROR,
    2511                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2512 ECB             :                  errmsg("input is out of range")));
    2513                 : 
    2514 CBC          54 :     INIT_DEGREE_CONSTANTS();
    2515                 : 
    2516                 :     /* Reduce the range of the input to [0,90] degrees */
    2517 GBC          54 :     arg1 = fmod(arg1, 360.0);
    2518 EUB             : 
    2519 GIC          54 :     if (arg1 < 0.0)
    2520                 :     {
    2521 ECB             :         /* tand(-x) = -tand(x) */
    2522 UIC           0 :         arg1 = -arg1;
    2523               0 :         sign = -sign;
    2524 ECB             :     }
    2525                 : 
    2526 GIC          54 :     if (arg1 > 180.0)
    2527                 :     {
    2528 ECB             :         /* tand(360-x) = -tand(x) */
    2529 GIC          18 :         arg1 = 360.0 - arg1;
    2530              18 :         sign = -sign;
    2531 ECB             :     }
    2532                 : 
    2533 GIC          54 :     if (arg1 > 90.0)
    2534                 :     {
    2535 ECB             :         /* tand(180-x) = -tand(x) */
    2536 CBC          18 :         arg1 = 180.0 - arg1;
    2537 GIC          18 :         sign = -sign;
    2538                 :     }
    2539                 : 
    2540              54 :     tan_arg1 = sind_q1(arg1) / cosd_q1(arg1);
    2541              54 :     result = sign * (tan_arg1 / tan_45);
    2542                 : 
    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                 :      */
    2548 CBC          54 :     if (result == 0.0)
    2549 GIC          18 :         result = 0.0;
    2550                 : 
    2551                 :     /* Not checking for overflow because tand(90) == Inf */
    2552                 : 
    2553              54 :     PG_RETURN_FLOAT8(result);
    2554                 : }
    2555                 : 
    2556 ECB             : 
    2557                 : /*
    2558                 :  *      degrees     - returns degrees converted from radians
    2559                 :  */
    2560                 : Datum
    2561 GIC          40 : degrees(PG_FUNCTION_ARGS)
    2562                 : {
    2563              40 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2564                 : 
    2565              40 :     PG_RETURN_FLOAT8(float8_div(arg1, RADIANS_PER_DEGREE));
    2566                 : }
    2567                 : 
    2568 ECB             : 
    2569                 : /*
    2570                 :  *      dpi             - returns the constant PI
    2571                 :  */
    2572                 : Datum
    2573 GIC          95 : dpi(PG_FUNCTION_ARGS)
    2574                 : {
    2575              95 :     PG_RETURN_FLOAT8(M_PI);
    2576                 : }
    2577                 : 
    2578 ECB             : 
    2579                 : /*
    2580                 :  *      radians     - returns radians converted from degrees
    2581                 :  */
    2582                 : Datum
    2583 GIC         955 : radians(PG_FUNCTION_ARGS)
    2584                 : {
    2585             955 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2586                 : 
    2587             955 :     PG_RETURN_FLOAT8(float8_mul(arg1, RADIANS_PER_DEGREE));
    2588                 : }
    2589                 : 
    2590                 : 
    2591                 : /* ========== HYPERBOLIC FUNCTIONS ========== */
    2592                 : 
    2593 ECB             : 
    2594                 : /*
    2595                 :  *      dsinh           - returns the hyperbolic sine of arg1
    2596                 :  */
    2597                 : Datum
    2598 CBC          12 : dsinh(PG_FUNCTION_ARGS)
    2599 ECB             : {
    2600 GIC          12 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2601                 :     float8      result;
    2602                 : 
    2603              12 :     errno = 0;
    2604              12 :     result = sinh(arg1);
    2605                 : 
    2606 ECB             :     /*
    2607                 :      * if an ERANGE error occurs, it means there is an overflow.  For sinh,
    2608 EUB             :      * the result should be either -infinity or infinity, depending on the
    2609                 :      * sign of arg1.
    2610                 :      */
    2611 GBC          12 :     if (errno == ERANGE)
    2612                 :     {
    2613 UIC           0 :         if (arg1 < 0)
    2614 LBC           0 :             result = -get_float8_infinity();
    2615                 :         else
    2616 UIC           0 :             result = get_float8_infinity();
    2617                 :     }
    2618                 : 
    2619 GIC          12 :     PG_RETURN_FLOAT8(result);
    2620                 : }
    2621                 : 
    2622 ECB             : 
    2623                 : /*
    2624                 :  *      dcosh           - returns the hyperbolic cosine of arg1
    2625                 :  */
    2626                 : Datum
    2627 CBC          12 : dcosh(PG_FUNCTION_ARGS)
    2628 ECB             : {
    2629 GIC          12 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2630                 :     float8      result;
    2631                 : 
    2632              12 :     errno = 0;
    2633              12 :     result = cosh(arg1);
    2634 ECB             : 
    2635 EUB             :     /*
    2636                 :      * if an ERANGE error occurs, it means there is an overflow.  As cosh is
    2637 ECB             :      * always positive, it always means the result is positive infinity.
    2638 EUB             :      */
    2639 GIC          12 :     if (errno == ERANGE)
    2640 LBC           0 :         result = get_float8_infinity();
    2641                 : 
    2642 GIC          12 :     if (unlikely(result == 0.0))
    2643 UIC           0 :         float_underflow_error();
    2644                 : 
    2645 GIC          12 :     PG_RETURN_FLOAT8(result);
    2646                 : }
    2647 ECB             : 
    2648                 : /*
    2649                 :  *      dtanh           - returns the hyperbolic tangent of arg1
    2650                 :  */
    2651                 : Datum
    2652 GIC          12 : dtanh(PG_FUNCTION_ARGS)
    2653                 : {
    2654              12 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2655 ECB             :     float8      result;
    2656                 : 
    2657                 :     /*
    2658 EUB             :      * For tanh, we don't need an errno check because it never overflows.
    2659                 :      */
    2660 CBC          12 :     result = tanh(arg1);
    2661                 : 
    2662 GIC          12 :     if (unlikely(isinf(result)))
    2663 UIC           0 :         float_overflow_error();
    2664                 : 
    2665 GIC          12 :     PG_RETURN_FLOAT8(result);
    2666                 : }
    2667 ECB             : 
    2668                 : /*
    2669                 :  *      dasinh          - returns the inverse hyperbolic sine of arg1
    2670                 :  */
    2671                 : Datum
    2672 GIC          12 : dasinh(PG_FUNCTION_ARGS)
    2673                 : {
    2674              12 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2675 ECB             :     float8      result;
    2676                 : 
    2677                 :     /*
    2678                 :      * For asinh, we don't need an errno check because it never overflows.
    2679                 :      */
    2680 GIC          12 :     result = asinh(arg1);
    2681                 : 
    2682              12 :     PG_RETURN_FLOAT8(result);
    2683                 : }
    2684 ECB             : 
    2685                 : /*
    2686                 :  *      dacosh          - returns the inverse hyperbolic cosine of arg1
    2687                 :  */
    2688                 : Datum
    2689 GIC           9 : dacosh(PG_FUNCTION_ARGS)
    2690                 : {
    2691               9 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2692                 :     float8      result;
    2693                 : 
    2694                 :     /*
    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                 :      */
    2700 CBC           9 :     if (arg1 < 1.0)
    2701 GIC           3 :         ereport(ERROR,
    2702 ECB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2703                 :                  errmsg("input is out of range")));
    2704                 : 
    2705 GIC           6 :     result = acosh(arg1);
    2706                 : 
    2707               6 :     PG_RETURN_FLOAT8(result);
    2708                 : }
    2709 ECB             : 
    2710                 : /*
    2711                 :  *      datanh          - returns the inverse hyperbolic tangent of arg1
    2712                 :  */
    2713                 : Datum
    2714 GIC          12 : datanh(PG_FUNCTION_ARGS)
    2715                 : {
    2716              12 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    2717                 :     float8      result;
    2718                 : 
    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                 :      */
    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                 : 
    2729 ECB             :     /*
    2730 EUB             :      * Also handle the infinity cases ourselves; this is helpful because old
    2731 ECB             :      * glibc versions may produce the wrong errno for this.  All other inputs
    2732 EUB             :      * cannot produce an error.
    2733                 :      */
    2734 CBC           6 :     if (arg1 == -1.0)
    2735 UIC           0 :         result = -get_float8_infinity();
    2736 CBC           6 :     else if (arg1 == 1.0)
    2737 UIC           0 :         result = get_float8_infinity();
    2738                 :     else
    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)
    2750 ECB             :  */
    2751                 : Datum
    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)))
    2763 UNC           0 :         float_overflow_error();
    2764                 : 
    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)))
    2783 UNC           0 :         float_overflow_error();
    2784                 : 
    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
    2796          445537 : initialize_drandom_seed(void)
    2797                 : {
    2798                 :     /* Initialize random seed, if not done yet in this process */
    2799 GIC      445537 :     if (unlikely(!drandom_seed_set))
    2800 ECB             :     {
    2801                 :         /*
    2802                 :          * If possible, initialize the seed using high-quality random bits.
    2803 EUB             :          * Should that fail for some reason, we fall back on a lower-quality
    2804                 :          * seed based on current time and PID.
    2805 ECB             :          */
    2806 GIC          52 :         if (unlikely(!pg_prng_strong_seed(&drandom_seed)))
    2807                 :         {
    2808 UIC           0 :             TimestampTz now = GetCurrentTimestamp();
    2809                 :             uint64      iseed;
    2810                 : 
    2811                 :             /* Mix the PID with the most predictable bits of the timestamp */
    2812 LBC           0 :             iseed = (uint64) now ^ ((uint64) MyProcPid << 32);
    2813 UIC           0 :             pg_prng_seed(&drandom_seed, iseed);
    2814 ECB             :         }
    2815 GIC          52 :         drandom_seed_set = true;
    2816                 :     }
    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) */
    2830 GIC      438877 :     result = pg_prng_double(&drandom_seed);
    2831 ECB             : 
    2832 GIC      438877 :     PG_RETURN_FLOAT8(result);
    2833 ECB             : }
    2834 EUB             : 
    2835                 : /*
    2836                 :  *      drandom_normal  - returns a random number from a normal distribution
    2837                 :  */
    2838                 : Datum
    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                 : 
    2857 ECB             : /*
    2858                 :  *      setseed     - set seed for the random number generator
    2859                 :  */
    2860                 : Datum
    2861 GIC           4 : setseed(PG_FUNCTION_ARGS)
    2862                 : {
    2863               4 :     float8      seed = PG_GETARG_FLOAT8(0);
    2864                 : 
    2865               4 :     if (seed < -1 || seed > 1 || isnan(seed))
    2866 UIC           0 :         ereport(ERROR,
    2867                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2868 ECB             :                  errmsg("setseed parameter %g is out of allowed range [-1,1]",
    2869                 :                         seed)));
    2870                 : 
    2871 CBC           4 :     pg_prng_fseed(&drandom_seed, seed);
    2872 GIC           4 :     drandom_seed_set = true;
    2873                 : 
    2874               4 :     PG_RETURN_VOID();
    2875                 : }
    2876                 : 
    2877                 : 
    2878 ECB             : 
    2879                 : /*
    2880 EUB             :  *      =========================
    2881                 :  *      FLOAT AGGREGATE OPERATORS
    2882                 :  *      =========================
    2883                 :  *
    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()
    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
    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                 :  *
    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.
    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                 :  */
    2926                 : 
    2927                 : static float8 *
    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
    2933 ECB             :      * going to look like a C array of N float8 values.
    2934                 :      */
    2935 CBC         746 :     if (ARR_NDIM(transarray) != 1 ||
    2936 GIC         746 :         ARR_DIMS(transarray)[0] != n ||
    2937 CBC         746 :         ARR_HASNULL(transarray) ||
    2938 GBC         746 :         ARR_ELEMTYPE(transarray) != FLOAT8OID)
    2939 UIC           0 :         elog(ERROR, "%s: expected %d-element float8 array", caller, n);
    2940 GIC         746 :     return (float8 *) ARR_DATA_PTR(transarray);
    2941                 : }
    2942                 : 
    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
    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                 : 
    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)
    3000 ECB             :     {
    3001 GIC           3 :         N = N1;
    3002               3 :         Sx = Sx1;
    3003               3 :         Sxx = Sxx1;
    3004                 :     }
    3005                 :     else
    3006                 :     {
    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;
    3011 GBC           3 :         if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
    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                 :      */
    3020 GIC           9 :     if (AggCheckCallContext(fcinfo, NULL))
    3021                 :     {
    3022 UIC           0 :         transvalues1[0] = N;
    3023               0 :         transvalues1[1] = Sx;
    3024 LBC           0 :         transvalues1[2] = Sxx;
    3025                 : 
    3026               0 :         PG_RETURN_ARRAYTYPE_P(transarray1);
    3027 ECB             :     }
    3028                 :     else
    3029                 :     {
    3030                 :         Datum       transdatums[3];
    3031                 :         ArrayType  *result;
    3032                 : 
    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                 : 
    3041 CBC           9 :         PG_RETURN_ARRAYTYPE_P(result);
    3042 ECB             :     }
    3043                 : }
    3044                 : 
    3045                 : Datum
    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);
    3050 ECB             :     float8     *transvalues;
    3051                 :     float8      N,
    3052                 :                 Sx,
    3053                 :                 Sxx,
    3054                 :                 tmp;
    3055                 : 
    3056 GIC         181 :     transvalues = check_float8_array(transarray, "float8_accum", 3);
    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                 :      */
    3065 CBC         181 :     N += 1.0;
    3066 GIC         181 :     Sx += newval;
    3067 CBC         181 :     if (transvalues[0] > 0.0)
    3068 ECB             :     {
    3069 CBC         132 :         tmp = newval * N - Sx;
    3070 GIC         132 :         Sxx += tmp * tmp / (N * transvalues[0]);
    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                 :          */
    3078 GIC         132 :         if (isinf(Sx) || isinf(Sxx))
    3079 ECB             :         {
    3080 CBC          12 :             if (!isinf(transvalues[1]) && !isinf(newval))
    3081 LBC           0 :                 float_overflow_error();
    3082 ECB             : 
    3083 CBC          12 :             Sxx = get_float8_nan();
    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
    3092 ECB             :          * more inputs.
    3093                 :          */
    3094 GBC          49 :         if (isnan(newval) || isinf(newval))
    3095              24 :             Sxx = get_float8_nan();
    3096 EUB             :     }
    3097                 : 
    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                 :      */
    3103 GIC         181 :     if (AggCheckCallContext(fcinfo, NULL))
    3104                 :     {
    3105 CBC         178 :         transvalues[0] = N;
    3106             178 :         transvalues[1] = Sx;
    3107             178 :         transvalues[2] = Sxx;
    3108                 : 
    3109             178 :         PG_RETURN_ARRAYTYPE_P(transarray);
    3110                 :     }
    3111                 :     else
    3112                 :     {
    3113 ECB             :         Datum       transdatums[3];
    3114                 :         ArrayType  *result;
    3115                 : 
    3116 GIC           3 :         transdatums[0] = Float8GetDatumFast(N);
    3117               3 :         transdatums[1] = Float8GetDatumFast(Sx);
    3118 CBC           3 :         transdatums[2] = Float8GetDatumFast(Sxx);
    3119                 : 
    3120               3 :         result = construct_array(transdatums, 3,
    3121 ECB             :                                  FLOAT8OID,
    3122                 :                                  sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);
    3123                 : 
    3124 GIC           3 :         PG_RETURN_ARRAYTYPE_P(result);
    3125                 :     }
    3126                 : }
    3127                 : 
    3128 ECB             : Datum
    3129 CBC         144 : float4_accum(PG_FUNCTION_ARGS)
    3130 ECB             : {
    3131 CBC         144 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3132                 : 
    3133                 :     /* do computations as float8 */
    3134 GIC         144 :     float8      newval = PG_GETARG_FLOAT4(1);
    3135                 :     float8     *transvalues;
    3136                 :     float8      N,
    3137 ECB             :                 Sx,
    3138                 :                 Sxx,
    3139                 :                 tmp;
    3140                 : 
    3141 CBC         144 :     transvalues = check_float8_array(transarray, "float4_accum", 3);
    3142             144 :     N = transvalues[0];
    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                 :      */
    3150 CBC         144 :     N += 1.0;
    3151 GIC         144 :     Sx += newval;
    3152 CBC         144 :     if (transvalues[0] > 0.0)
    3153 EUB             :     {
    3154 GIC         102 :         tmp = newval * N - Sx;
    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                 :          */
    3163 GIC         102 :         if (isinf(Sx) || isinf(Sxx))
    3164                 :         {
    3165 UIC           0 :             if (!isinf(transvalues[1]) && !isinf(newval))
    3166 LBC           0 :                 float_overflow_error();
    3167 ECB             : 
    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
    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                 :          */
    3179 CBC          42 :         if (isnan(newval) || isinf(newval))
    3180 GIC          12 :             Sxx = get_float8_nan();
    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                 :      */
    3188 CBC         144 :     if (AggCheckCallContext(fcinfo, NULL))
    3189 ECB             :     {
    3190 CBC         144 :         transvalues[0] = N;
    3191 GIC         144 :         transvalues[1] = Sx;
    3192 CBC         144 :         transvalues[2] = Sxx;
    3193                 : 
    3194 GIC         144 :         PG_RETURN_ARRAYTYPE_P(transarray);
    3195                 :     }
    3196 ECB             :     else
    3197                 :     {
    3198                 :         Datum       transdatums[3];
    3199                 :         ArrayType  *result;
    3200                 : 
    3201 LBC           0 :         transdatums[0] = Float8GetDatumFast(N);
    3202 UIC           0 :         transdatums[1] = Float8GetDatumFast(Sx);
    3203 LBC           0 :         transdatums[2] = Float8GetDatumFast(Sxx);
    3204                 : 
    3205 UIC           0 :         result = construct_array(transdatums, 3,
    3206 ECB             :                                  FLOAT8OID,
    3207                 :                                  sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);
    3208                 : 
    3209 UIC           0 :         PG_RETURN_ARRAYTYPE_P(result);
    3210                 :     }
    3211                 : }
    3212                 : 
    3213 ECB             : Datum
    3214 CBC          31 : float8_avg(PG_FUNCTION_ARGS)
    3215 ECB             : {
    3216 CBC          31 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3217                 :     float8     *transvalues;
    3218                 :     float8      N,
    3219                 :                 Sx;
    3220                 : 
    3221 GIC          31 :     transvalues = check_float8_array(transarray, "float8_avg", 3);
    3222 CBC          31 :     N = transvalues[0];
    3223              31 :     Sx = transvalues[1];
    3224 ECB             :     /* ignore Sxx */
    3225                 : 
    3226                 :     /* SQL defines AVG of no values to be NULL */
    3227 CBC          31 :     if (N == 0.0)
    3228 GIC           3 :         PG_RETURN_NULL();
    3229                 : 
    3230              28 :     PG_RETURN_FLOAT8(Sx / N);
    3231                 : }
    3232                 : 
    3233                 : Datum
    3234              42 : float8_var_pop(PG_FUNCTION_ARGS)
    3235 ECB             : {
    3236 GIC          42 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3237 EUB             :     float8     *transvalues;
    3238                 :     float8      N,
    3239                 :                 Sxx;
    3240                 : 
    3241 GIC          42 :     transvalues = check_float8_array(transarray, "float8_var_pop", 3);
    3242              42 :     N = transvalues[0];
    3243                 :     /* ignore Sx */
    3244              42 :     Sxx = transvalues[2];
    3245                 : 
    3246                 :     /* Population variance is undefined when N is 0, so return NULL */
    3247              42 :     if (N == 0.0)
    3248 UIC           0 :         PG_RETURN_NULL();
    3249                 : 
    3250                 :     /* Note that Sxx is guaranteed to be non-negative */
    3251 ECB             : 
    3252 CBC          42 :     PG_RETURN_FLOAT8(Sxx / N);
    3253                 : }
    3254                 : 
    3255                 : Datum
    3256 GIC          21 : float8_var_samp(PG_FUNCTION_ARGS)
    3257                 : {
    3258              21 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3259                 :     float8     *transvalues;
    3260 ECB             :     float8      N,
    3261                 :                 Sxx;
    3262                 : 
    3263 CBC          21 :     transvalues = check_float8_array(transarray, "float8_var_samp", 3);
    3264              21 :     N = transvalues[0];
    3265                 :     /* ignore Sx */
    3266              21 :     Sxx = transvalues[2];
    3267                 : 
    3268                 :     /* Sample variance is undefined when N is 0 or 1, so return NULL */
    3269 GIC          21 :     if (N <= 1.0)
    3270              18 :         PG_RETURN_NULL();
    3271                 : 
    3272                 :     /* Note that Sxx is guaranteed to be non-negative */
    3273 EUB             : 
    3274 GBC           3 :     PG_RETURN_FLOAT8(Sxx / (N - 1.0));
    3275 EUB             : }
    3276                 : 
    3277                 : Datum
    3278 GIC          21 : float8_stddev_pop(PG_FUNCTION_ARGS)
    3279                 : {
    3280              21 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3281 EUB             :     float8     *transvalues;
    3282                 :     float8      N,
    3283                 :                 Sxx;
    3284                 : 
    3285 GIC          21 :     transvalues = check_float8_array(transarray, "float8_stddev_pop", 3);
    3286 CBC          21 :     N = transvalues[0];
    3287                 :     /* ignore Sx */
    3288              21 :     Sxx = transvalues[2];
    3289                 : 
    3290                 :     /* Population stddev is undefined when N is 0, so return NULL */
    3291 GIC          21 :     if (N == 0.0)
    3292 UIC           0 :         PG_RETURN_NULL();
    3293 ECB             : 
    3294                 :     /* Note that Sxx is guaranteed to be non-negative */
    3295                 : 
    3296 GIC          21 :     PG_RETURN_FLOAT8(sqrt(Sxx / N));
    3297                 : }
    3298                 : 
    3299 ECB             : Datum
    3300 CBC          24 : float8_stddev_samp(PG_FUNCTION_ARGS)
    3301                 : {
    3302              24 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3303                 :     float8     *transvalues;
    3304                 :     float8      N,
    3305                 :                 Sxx;
    3306 ECB             : 
    3307 GIC          24 :     transvalues = check_float8_array(transarray, "float8_stddev_samp", 3);
    3308 CBC          24 :     N = transvalues[0];
    3309                 :     /* ignore Sx */
    3310 GIC          24 :     Sxx = transvalues[2];
    3311                 : 
    3312                 :     /* Sample stddev is undefined when N is 0 or 1, so return NULL */
    3313 CBC          24 :     if (N <= 1.0)
    3314              18 :         PG_RETURN_NULL();
    3315                 : 
    3316 ECB             :     /* Note that Sxx is guaranteed to be non-negative */
    3317                 : 
    3318 GIC           6 :     PG_RETURN_FLOAT8(sqrt(Sxx / (N - 1.0)));
    3319 ECB             : }
    3320 EUB             : 
    3321                 : /*
    3322                 :  *      =========================
    3323                 :  *      SQL2003 BINARY AGGREGATES
    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.
    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                 :  *
    3335                 :  * It might seem attractive to optimize this by having multiple accumulator
    3336                 :  * functions that only calculate the sums actually needed.  But on most
    3337                 :  * modern machines, a couple of extra floating-point multiplies will be
    3338                 :  * insignificant compared to the other per-tuple overhead, so I've chosen
    3339                 :  * to minimize code space instead.
    3340                 :  */
    3341                 : 
    3342                 : Datum
    3343 GIC         159 : float8_regr_accum(PG_FUNCTION_ARGS)
    3344                 : {
    3345             159 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3346 CBC         159 :     float8      newvalY = PG_GETARG_FLOAT8(1);
    3347 GIC         159 :     float8      newvalX = PG_GETARG_FLOAT8(2);
    3348                 :     float8     *transvalues;
    3349                 :     float8      N,
    3350 ECB             :                 Sx,
    3351                 :                 Sxx,
    3352                 :                 Sy,
    3353                 :                 Syy,
    3354                 :                 Sxy,
    3355                 :                 tmpX,
    3356                 :                 tmpY,
    3357                 :                 scale;
    3358                 : 
    3359 GIC         159 :     transvalues = check_float8_array(transarray, "float8_regr_accum", 6);
    3360 CBC         159 :     N = transvalues[0];
    3361 GIC         159 :     Sx = transvalues[1];
    3362             159 :     Sxx = transvalues[2];
    3363 CBC         159 :     Sy = transvalues[3];
    3364 GBC         159 :     Syy = transvalues[4];
    3365 GIC         159 :     Sxy = transvalues[5];
    3366                 : 
    3367                 :     /*
    3368 ECB             :      * Use the Youngs-Cramer algorithm to incorporate the new values into the
    3369                 :      * transition values.
    3370                 :      */
    3371 GIC         159 :     N += 1.0;
    3372 CBC         159 :     Sx += newvalX;
    3373 GIC         159 :     Sy += newvalY;
    3374 CBC         159 :     if (transvalues[0] > 0.0)
    3375                 :     {
    3376 GIC         105 :         tmpX = newvalX * N - Sx;
    3377             105 :         tmpY = newvalY * N - Sy;
    3378             105 :         scale = 1.0 / (N * transvalues[0]);
    3379 CBC         105 :         Sxx += tmpX * tmpX * scale;
    3380             105 :         Syy += tmpY * tmpY * scale;
    3381 GIC         105 :         Sxy += tmpX * tmpY * scale;
    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                 :          */
    3389 GIC         105 :         if (isinf(Sx) || isinf(Sxx) || isinf(Sy) || isinf(Syy) || isinf(Sxy))
    3390 ECB             :         {
    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)))
    3398               0 :                 float_overflow_error();
    3399                 : 
    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.
    3415 ECB             :          */
    3416 GIC          54 :         if (isnan(newvalX) || isinf(newvalX))
    3417 CBC          12 :             Sxx = Sxy = get_float8_nan();
    3418              54 :         if (isnan(newvalY) || isinf(newvalY))
    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                 :      */
    3427 GIC         159 :     if (AggCheckCallContext(fcinfo, NULL))
    3428                 :     {
    3429             156 :         transvalues[0] = N;
    3430             156 :         transvalues[1] = Sx;
    3431 CBC         156 :         transvalues[2] = Sxx;
    3432             156 :         transvalues[3] = Sy;
    3433             156 :         transvalues[4] = Syy;
    3434             156 :         transvalues[5] = Sxy;
    3435 ECB             : 
    3436 CBC         156 :         PG_RETURN_ARRAYTYPE_P(transarray);
    3437 ECB             :     }
    3438                 :     else
    3439                 :     {
    3440                 :         Datum       transdatums[6];
    3441                 :         ArrayType  *result;
    3442                 : 
    3443 CBC           3 :         transdatums[0] = Float8GetDatumFast(N);
    3444               3 :         transdatums[1] = Float8GetDatumFast(Sx);
    3445               3 :         transdatums[2] = Float8GetDatumFast(Sxx);
    3446               3 :         transdatums[3] = Float8GetDatumFast(Sy);
    3447 GIC           3 :         transdatums[4] = Float8GetDatumFast(Syy);
    3448 CBC           3 :         transdatums[5] = Float8GetDatumFast(Sxy);
    3449 ECB             : 
    3450 CBC           3 :         result = construct_array(transdatums, 6,
    3451 ECB             :                                  FLOAT8OID,
    3452                 :                                  sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);
    3453                 : 
    3454 GIC           3 :         PG_RETURN_ARRAYTYPE_P(result);
    3455                 :     }
    3456                 : }
    3457                 : 
    3458                 : /*
    3459                 :  * float8_regr_combine
    3460                 :  *
    3461 ECB             :  * An aggregate combine function used to combine two 6 fields
    3462                 :  * aggregate transition data into a single transition data.
    3463 EUB             :  * This function is used only in two stage aggregation and
    3464                 :  * shouldn't be called outside aggregate context.
    3465                 :  */
    3466                 : Datum
    3467 GBC           9 : float8_regr_combine(PG_FUNCTION_ARGS)
    3468 EUB             : {
    3469 GBC           9 :     ArrayType  *transarray1 = PG_GETARG_ARRAYTYPE_P(0);
    3470               9 :     ArrayType  *transarray2 = PG_GETARG_ARRAYTYPE_P(1);
    3471                 :     float8     *transvalues1;
    3472 EUB             :     float8     *transvalues2;
    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,
    3488 ECB             :                 Sx,
    3489                 :                 Sxx,
    3490                 :                 Sy,
    3491 EUB             :                 Syy,
    3492                 :                 Sxy;
    3493                 : 
    3494 GIC           9 :     transvalues1 = check_float8_array(transarray1, "float8_regr_combine", 6);
    3495               9 :     transvalues2 = check_float8_array(transarray2, "float8_regr_combine", 6);
    3496                 : 
    3497               9 :     N1 = transvalues1[0];
    3498               9 :     Sx1 = transvalues1[1];
    3499 CBC           9 :     Sxx1 = transvalues1[2];
    3500 GIC           9 :     Sy1 = transvalues1[3];
    3501 CBC           9 :     Syy1 = transvalues1[4];
    3502               9 :     Sxy1 = transvalues1[5];
    3503 ECB             : 
    3504 CBC           9 :     N2 = transvalues2[0];
    3505               9 :     Sx2 = transvalues2[1];
    3506               9 :     Sxx2 = transvalues2[2];
    3507 GIC           9 :     Sy2 = transvalues2[3];
    3508 CBC           9 :     Syy2 = transvalues2[4];
    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                 :      *
    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                 :      */
    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;
    3539 CBC           3 :         Sx = Sx1;
    3540 GIC           3 :         Sxx = Sxx1;
    3541 CBC           3 :         Sy = Sy1;
    3542               3 :         Syy = Syy1;
    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;
    3551               3 :         if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
    3552 UIC           0 :             float_overflow_error();
    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;
    3556               3 :         if (unlikely(isinf(Syy)) && !isinf(Syy1) && !isinf(Syy2))
    3557 UIC           0 :             float_overflow_error();
    3558 GIC           3 :         Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N;
    3559               3 :         if (unlikely(isinf(Sxy)) && !isinf(Sxy1) && !isinf(Sxy2))
    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
    3566 ECB             :      * new array with the updated transition data and return it.
    3567                 :      */
    3568 GIC           9 :     if (AggCheckCallContext(fcinfo, NULL))
    3569 ECB             :     {
    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;
    3575 UIC           0 :         transvalues1[5] = Sxy;
    3576 ECB             : 
    3577 LBC           0 :         PG_RETURN_ARRAYTYPE_P(transarray1);
    3578 ECB             :     }
    3579                 :     else
    3580                 :     {
    3581                 :         Datum       transdatums[6];
    3582                 :         ArrayType  *result;
    3583                 : 
    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                 : 
    3599 ECB             : 
    3600                 : Datum
    3601 CBC          15 : float8_regr_sxx(PG_FUNCTION_ARGS)
    3602 ECB             : {
    3603 CBC          15 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3604 ECB             :     float8     *transvalues;
    3605                 :     float8      N,
    3606                 :                 Sxx;
    3607                 : 
    3608 CBC          15 :     transvalues = check_float8_array(transarray, "float8_regr_sxx", 6);
    3609 GIC          15 :     N = transvalues[0];
    3610 CBC          15 :     Sxx = transvalues[2];
    3611 ECB             : 
    3612                 :     /* if N is 0 we should return NULL */
    3613 CBC          15 :     if (N < 1.0)
    3614 LBC           0 :         PG_RETURN_NULL();
    3615 ECB             : 
    3616                 :     /* Note that Sxx is guaranteed to be non-negative */
    3617                 : 
    3618 GIC          15 :     PG_RETURN_FLOAT8(Sxx);
    3619 ECB             : }
    3620                 : 
    3621                 : Datum
    3622 CBC          15 : float8_regr_syy(PG_FUNCTION_ARGS)
    3623 ECB             : {
    3624 GBC          15 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3625 ECB             :     float8     *transvalues;
    3626                 :     float8      N,
    3627                 :                 Syy;
    3628                 : 
    3629 GBC          15 :     transvalues = check_float8_array(transarray, "float8_regr_syy", 6);
    3630 CBC          15 :     N = transvalues[0];
    3631              15 :     Syy = transvalues[4];
    3632 EUB             : 
    3633                 :     /* if N is 0 we should return NULL */
    3634 GIC          15 :     if (N < 1.0)
    3635 UIC           0 :         PG_RETURN_NULL();
    3636                 : 
    3637                 :     /* Note that Syy is guaranteed to be non-negative */
    3638                 : 
    3639 GIC          15 :     PG_RETURN_FLOAT8(Syy);
    3640 ECB             : }
    3641                 : 
    3642 EUB             : Datum
    3643 GBC          15 : float8_regr_sxy(PG_FUNCTION_ARGS)
    3644 EUB             : {
    3645 GBC          15 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3646 EUB             :     float8     *transvalues;
    3647                 :     float8      N,
    3648                 :                 Sxy;
    3649                 : 
    3650 GIC          15 :     transvalues = check_float8_array(transarray, "float8_regr_sxy", 6);
    3651              15 :     N = transvalues[0];
    3652              15 :     Sxy = transvalues[5];
    3653                 : 
    3654                 :     /* if N is 0 we should return NULL */
    3655              15 :     if (N < 1.0)
    3656 LBC           0 :         PG_RETURN_NULL();
    3657 ECB             : 
    3658                 :     /* A negative result is valid here */
    3659                 : 
    3660 CBC          15 :     PG_RETURN_FLOAT8(Sxy);
    3661 ECB             : }
    3662                 : 
    3663                 : Datum
    3664 GIC           3 : float8_regr_avgx(PG_FUNCTION_ARGS)
    3665                 : {
    3666               3 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3667 ECB             :     float8     *transvalues;
    3668                 :     float8      N,
    3669                 :                 Sx;
    3670                 : 
    3671 GIC           3 :     transvalues = check_float8_array(transarray, "float8_regr_avgx", 6);
    3672               3 :     N = transvalues[0];
    3673 CBC           3 :     Sx = transvalues[1];
    3674                 : 
    3675 ECB             :     /* if N is 0 we should return NULL */
    3676 GIC           3 :     if (N < 1.0)
    3677 UIC           0 :         PG_RETURN_NULL();
    3678                 : 
    3679 GIC           3 :     PG_RETURN_FLOAT8(Sx / N);
    3680 ECB             : }
    3681                 : 
    3682                 : Datum
    3683 GIC           3 : float8_regr_avgy(PG_FUNCTION_ARGS)
    3684                 : {
    3685 CBC           3 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3686 EUB             :     float8     *transvalues;
    3687                 :     float8      N,
    3688                 :                 Sy;
    3689                 : 
    3690 CBC           3 :     transvalues = check_float8_array(transarray, "float8_regr_avgy", 6);
    3691 GIC           3 :     N = transvalues[0];
    3692               3 :     Sy = transvalues[3];
    3693                 : 
    3694 ECB             :     /* if N is 0 we should return NULL */
    3695 GIC           3 :     if (N < 1.0)
    3696 LBC           0 :         PG_RETURN_NULL();
    3697                 : 
    3698 GIC           3 :     PG_RETURN_FLOAT8(Sy / N);
    3699                 : }
    3700                 : 
    3701 ECB             : Datum
    3702 CBC          12 : float8_covar_pop(PG_FUNCTION_ARGS)
    3703 ECB             : {
    3704 GIC          12 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3705                 :     float8     *transvalues;
    3706 ECB             :     float8      N,
    3707 EUB             :                 Sxy;
    3708                 : 
    3709 GIC          12 :     transvalues = check_float8_array(transarray, "float8_covar_pop", 6);
    3710              12 :     N = transvalues[0];
    3711 CBC          12 :     Sxy = transvalues[5];
    3712                 : 
    3713                 :     /* if N is 0 we should return NULL */
    3714 GIC          12 :     if (N < 1.0)
    3715 LBC           0 :         PG_RETURN_NULL();
    3716                 : 
    3717 CBC          12 :     PG_RETURN_FLOAT8(Sxy / N);
    3718                 : }
    3719                 : 
    3720                 : Datum
    3721 GIC          12 : float8_covar_samp(PG_FUNCTION_ARGS)
    3722 ECB             : {
    3723 CBC          12 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3724 ECB             :     float8     *transvalues;
    3725                 :     float8      N,
    3726                 :                 Sxy;
    3727                 : 
    3728 GBC          12 :     transvalues = check_float8_array(transarray, "float8_covar_samp", 6);
    3729 GIC          12 :     N = transvalues[0];
    3730              12 :     Sxy = transvalues[5];
    3731                 : 
    3732 ECB             :     /* if N is <= 1 we should return NULL */
    3733 GIC          12 :     if (N < 2.0)
    3734               9 :         PG_RETURN_NULL();
    3735                 : 
    3736 CBC           3 :     PG_RETURN_FLOAT8(Sxy / (N - 1.0));
    3737                 : }
    3738 ECB             : 
    3739                 : Datum
    3740 GIC           3 : float8_corr(PG_FUNCTION_ARGS)
    3741                 : {
    3742               3 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3743 ECB             :     float8     *transvalues;
    3744                 :     float8      N,
    3745                 :                 Sxx,
    3746                 :                 Syy,
    3747                 :                 Sxy;
    3748                 : 
    3749 GBC           3 :     transvalues = check_float8_array(transarray, "float8_corr", 6);
    3750 GIC           3 :     N = transvalues[0];
    3751 CBC           3 :     Sxx = transvalues[2];
    3752 GIC           3 :     Syy = transvalues[4];
    3753               3 :     Sxy = transvalues[5];
    3754                 : 
    3755 ECB             :     /* if N is 0 we should return NULL */
    3756 GIC           3 :     if (N < 1.0)
    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 */
    3762 CBC           3 :     if (Sxx == 0 || Syy == 0)
    3763 LBC           0 :         PG_RETURN_NULL();
    3764 ECB             : 
    3765 GIC           3 :     PG_RETURN_FLOAT8(Sxy / sqrt(Sxx * Syy));
    3766                 : }
    3767 ECB             : 
    3768 EUB             : Datum
    3769 GIC           3 : float8_regr_r2(PG_FUNCTION_ARGS)
    3770 ECB             : {
    3771 GIC           3 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3772                 :     float8     *transvalues;
    3773                 :     float8      N,
    3774 ECB             :                 Sxx,
    3775                 :                 Syy,
    3776                 :                 Sxy;
    3777                 : 
    3778 GIC           3 :     transvalues = check_float8_array(transarray, "float8_regr_r2", 6);
    3779               3 :     N = transvalues[0];
    3780               3 :     Sxx = transvalues[2];
    3781 CBC           3 :     Syy = transvalues[4];
    3782               3 :     Sxy = transvalues[5];
    3783 ECB             : 
    3784                 :     /* if N is 0 we should return NULL */
    3785 GIC           3 :     if (N < 1.0)
    3786 LBC           0 :         PG_RETURN_NULL();
    3787 EUB             : 
    3788                 :     /* Note that Sxx and Syy are guaranteed to be non-negative */
    3789 ECB             : 
    3790                 :     /* per spec, return NULL for a vertical line */
    3791 GIC           3 :     if (Sxx == 0)
    3792 UIC           0 :         PG_RETURN_NULL();
    3793 ECB             : 
    3794                 :     /* per spec, return 1.0 for a horizontal line */
    3795 CBC           3 :     if (Syy == 0)
    3796 UIC           0 :         PG_RETURN_FLOAT8(1.0);
    3797                 : 
    3798 GIC           3 :     PG_RETURN_FLOAT8((Sxy * Sxy) / (Sxx * Syy));
    3799                 : }
    3800 ECB             : 
    3801                 : Datum
    3802 CBC           3 : float8_regr_slope(PG_FUNCTION_ARGS)
    3803                 : {
    3804 GIC           3 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3805 ECB             :     float8     *transvalues;
    3806                 :     float8      N,
    3807                 :                 Sxx,
    3808                 :                 Sxy;
    3809                 : 
    3810 GIC           3 :     transvalues = check_float8_array(transarray, "float8_regr_slope", 6);
    3811               3 :     N = transvalues[0];
    3812 CBC           3 :     Sxx = transvalues[2];
    3813 GIC           3 :     Sxy = transvalues[5];
    3814 ECB             : 
    3815                 :     /* if N is 0 we should return NULL */
    3816 GIC           3 :     if (N < 1.0)
    3817 UIC           0 :         PG_RETURN_NULL();
    3818                 : 
    3819                 :     /* Note that Sxx is guaranteed to be non-negative */
    3820                 : 
    3821 ECB             :     /* per spec, return NULL for a vertical line */
    3822 CBC           3 :     if (Sxx == 0)
    3823 LBC           0 :         PG_RETURN_NULL();
    3824 ECB             : 
    3825 CBC           3 :     PG_RETURN_FLOAT8(Sxy / Sxx);
    3826                 : }
    3827                 : 
    3828 ECB             : Datum
    3829 GBC           3 : float8_regr_intercept(PG_FUNCTION_ARGS)
    3830                 : {
    3831 GIC           3 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    3832                 :     float8     *transvalues;
    3833                 :     float8      N,
    3834 ECB             :                 Sx,
    3835 EUB             :                 Sxx,
    3836                 :                 Sy,
    3837 ECB             :                 Sxy;
    3838                 : 
    3839 GIC           3 :     transvalues = check_float8_array(transarray, "float8_regr_intercept", 6);
    3840               3 :     N = transvalues[0];
    3841 CBC           3 :     Sx = transvalues[1];
    3842 GIC           3 :     Sxx = transvalues[2];
    3843 CBC           3 :     Sy = transvalues[3];
    3844 GIC           3 :     Sxy = transvalues[5];
    3845                 : 
    3846                 :     /* if N is 0 we should return NULL */
    3847               3 :     if (N < 1.0)
    3848 UIC           0 :         PG_RETURN_NULL();
    3849                 : 
    3850 ECB             :     /* Note that Sxx is guaranteed to be non-negative */
    3851                 : 
    3852                 :     /* per spec, return NULL for a vertical line */
    3853 CBC           3 :     if (Sxx == 0)
    3854 LBC           0 :         PG_RETURN_NULL();
    3855                 : 
    3856 GIC           3 :     PG_RETURN_FLOAT8((Sy - Sx * Sxy / Sxx) / N);
    3857 ECB             : }
    3858 EUB             : 
    3859                 : 
    3860                 : /*
    3861                 :  *      ====================================
    3862                 :  *      MIXED-PRECISION ARITHMETIC OPERATORS
    3863 ECB             :  *      ====================================
    3864 EUB             :  */
    3865                 : 
    3866                 : /*
    3867 ECB             :  *      float48pl       - returns arg1 + arg2
    3868 EUB             :  *      float48mi       - returns arg1 - arg2
    3869                 :  *      float48mul      - returns arg1 * arg2
    3870 ECB             :  *      float48div      - returns arg1 / arg2
    3871                 :  */
    3872                 : Datum
    3873 GIC           3 : float48pl(PG_FUNCTION_ARGS)
    3874 ECB             : {
    3875 GIC           3 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    3876 CBC           3 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    3877                 : 
    3878 GIC           3 :     PG_RETURN_FLOAT8(float8_pl((float8) arg1, arg2));
    3879                 : }
    3880                 : 
    3881                 : Datum
    3882 LBC           0 : float48mi(PG_FUNCTION_ARGS)
    3883 ECB             : {
    3884 LBC           0 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    3885               0 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    3886                 : 
    3887 UIC           0 :     PG_RETURN_FLOAT8(float8_mi((float8) arg1, arg2));
    3888 ECB             : }
    3889 EUB             : 
    3890                 : Datum
    3891 UIC           0 : float48mul(PG_FUNCTION_ARGS)
    3892                 : {
    3893               0 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    3894 LBC           0 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    3895 EUB             : 
    3896 UIC           0 :     PG_RETURN_FLOAT8(float8_mul((float8) arg1, arg2));
    3897 ECB             : }
    3898                 : 
    3899                 : Datum
    3900 GIC           3 : float48div(PG_FUNCTION_ARGS)
    3901 ECB             : {
    3902 GIC           3 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    3903 CBC           3 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    3904                 : 
    3905 GIC           3 :     PG_RETURN_FLOAT8(float8_div((float8) arg1, arg2));
    3906                 : }
    3907                 : 
    3908                 : /*
    3909                 :  *      float84pl       - returns arg1 + arg2
    3910                 :  *      float84mi       - returns arg1 - arg2
    3911 ECB             :  *      float84mul      - returns arg1 * arg2
    3912                 :  *      float84div      - returns arg1 / arg2
    3913                 :  */
    3914                 : Datum
    3915 CBC           6 : float84pl(PG_FUNCTION_ARGS)
    3916 ECB             : {
    3917 GIC           6 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    3918               6 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    3919 ECB             : 
    3920 GBC           6 :     PG_RETURN_FLOAT8(float8_pl(arg1, (float8) arg2));
    3921                 : }
    3922                 : 
    3923                 : Datum
    3924 UIC           0 : float84mi(PG_FUNCTION_ARGS)
    3925 ECB             : {
    3926 UBC           0 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    3927 UIC           0 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    3928 ECB             : 
    3929 UIC           0 :     PG_RETURN_FLOAT8(float8_mi(arg1, (float8) arg2));
    3930                 : }
    3931                 : 
    3932                 : Datum
    3933               0 : float84mul(PG_FUNCTION_ARGS)
    3934                 : {
    3935               0 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    3936               0 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    3937                 : 
    3938               0 :     PG_RETURN_FLOAT8(float8_mul(arg1, (float8) arg2));
    3939                 : }
    3940                 : 
    3941                 : Datum
    3942 GIC           3 : float84div(PG_FUNCTION_ARGS)
    3943                 : {
    3944               3 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    3945 CBC           3 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    3946                 : 
    3947               3 :     PG_RETURN_FLOAT8(float8_div(arg1, (float8) arg2));
    3948 ECB             : }
    3949                 : 
    3950                 : /*
    3951                 :  *      ====================
    3952                 :  *      COMPARISON OPERATORS
    3953                 :  *      ====================
    3954 EUB             :  */
    3955                 : 
    3956                 : /*
    3957                 :  *      float48{eq,ne,lt,le,gt,ge}      - float4/float8 comparison operations
    3958                 :  */
    3959                 : Datum
    3960 GIC        1491 : float48eq(PG_FUNCTION_ARGS)
    3961                 : {
    3962            1491 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    3963 GBC        1491 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    3964                 : 
    3965            1491 :     PG_RETURN_BOOL(float8_eq((float8) arg1, arg2));
    3966 EUB             : }
    3967                 : 
    3968                 : Datum
    3969 GIC        9735 : float48ne(PG_FUNCTION_ARGS)
    3970                 : {
    3971            9735 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    3972 CBC        9735 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    3973                 : 
    3974            9735 :     PG_RETURN_BOOL(float8_ne((float8) arg1, arg2));
    3975 ECB             : }
    3976                 : 
    3977                 : Datum
    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                 : 
    3983            2134 :     PG_RETURN_BOOL(float8_lt((float8) arg1, arg2));
    3984                 : }
    3985                 : 
    3986                 : Datum
    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                 : 
    3992           12811 :     PG_RETURN_BOOL(float8_le((float8) arg1, arg2));
    3993                 : }
    3994                 : 
    3995                 : Datum
    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                 : 
    4001            2246 :     PG_RETURN_BOOL(float8_gt((float8) arg1, arg2));
    4002                 : }
    4003                 : 
    4004                 : Datum
    4005            2446 : float48ge(PG_FUNCTION_ARGS)
    4006                 : {
    4007            2446 :     float4      arg1 = PG_GETARG_FLOAT4(0);
    4008            2446 :     float8      arg2 = PG_GETARG_FLOAT8(1);
    4009                 : 
    4010            2446 :     PG_RETURN_BOOL(float8_ge((float8) arg1, arg2));
    4011                 : }
    4012                 : 
    4013                 : /*
    4014 ECB             :  *      float84{eq,ne,lt,le,gt,ge}      - float8/float4 comparison operations
    4015                 :  */
    4016                 : Datum
    4017 CBC         906 : float84eq(PG_FUNCTION_ARGS)
    4018                 : {
    4019             906 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    4020 GIC         906 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    4021                 : 
    4022             906 :     PG_RETURN_BOOL(float8_eq(arg1, (float8) arg2));
    4023                 : }
    4024                 : 
    4025                 : Datum
    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                 : 
    4031               0 :     PG_RETURN_BOOL(float8_ne(arg1, (float8) arg2));
    4032 ECB             : }
    4033                 : 
    4034                 : Datum
    4035 CBC        1599 : float84lt(PG_FUNCTION_ARGS)
    4036                 : {
    4037            1599 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    4038 GIC        1599 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    4039                 : 
    4040            1599 :     PG_RETURN_BOOL(float8_lt(arg1, (float8) arg2));
    4041 ECB             : }
    4042                 : 
    4043                 : Datum
    4044 CBC        1899 : float84le(PG_FUNCTION_ARGS)
    4045                 : {
    4046            1899 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    4047 GIC        1899 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    4048                 : 
    4049            1899 :     PG_RETURN_BOOL(float8_le(arg1, (float8) arg2));
    4050 ECB             : }
    4051                 : 
    4052                 : Datum
    4053 CBC        1599 : float84gt(PG_FUNCTION_ARGS)
    4054                 : {
    4055            1599 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    4056 GIC        1599 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    4057                 : 
    4058            1599 :     PG_RETURN_BOOL(float8_gt(arg1, (float8) arg2));
    4059 ECB             : }
    4060                 : 
    4061                 : Datum
    4062 CBC        1602 : float84ge(PG_FUNCTION_ARGS)
    4063                 : {
    4064            1602 :     float8      arg1 = PG_GETARG_FLOAT8(0);
    4065 GIC        1602 :     float4      arg2 = PG_GETARG_FLOAT4(1);
    4066                 : 
    4067            1602 :     PG_RETURN_BOOL(float8_ge(arg1, (float8) arg2));
    4068 ECB             : }
    4069                 : 
    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
    4085 GIC         432 : width_bucket_float8(PG_FUNCTION_ARGS)
    4086                 : {
    4087             432 :     float8      operand = PG_GETARG_FLOAT8(0);
    4088             432 :     float8      bound1 = PG_GETARG_FLOAT8(1);
    4089 CBC         432 :     float8      bound2 = PG_GETARG_FLOAT8(2);
    4090 GIC         432 :     int32       count = PG_GETARG_INT32(3);
    4091 ECB             :     int32       result;
    4092                 : 
    4093 GNC         432 :     if (count <= 0)
    4094 CBC           6 :         ereport(ERROR,
    4095                 :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    4096                 :                  errmsg("count must be greater than zero")));
    4097                 : 
    4098 GBC         426 :     if (isnan(operand) || isnan(bound1) || isnan(bound2))
    4099 GIC           3 :         ereport(ERROR,
    4100 EUB             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    4101                 :                  errmsg("operand, lower bound, and upper bound cannot be NaN")));
    4102                 : 
    4103                 :     /* Note that we allow "operand" to be infinite */
    4104 GIC         423 :     if (isinf(bound1) || isinf(bound2))
    4105               9 :         ereport(ERROR,
    4106                 :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    4107 ECB             :                  errmsg("lower and upper bounds must be finite")));
    4108                 : 
    4109 CBC         414 :     if (bound1 < bound2)
    4110 ECB             :     {
    4111 GIC         297 :         if (operand < bound1)
    4112 CBC          57 :             result = 0;
    4113 GIC         240 :         else if (operand >= bound2)
    4114                 :         {
    4115              60 :             if (pg_add_s32_overflow(count, 1, &result))
    4116 CBC           3 :                 ereport(ERROR,
    4117                 :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    4118 ECB             :                          errmsg("integer out of range")));
    4119                 :         }
    4120                 :         else
    4121                 :         {
    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                 :     }
    4147 GIC         117 :     else if (bound1 > bound2)
    4148                 :     {
    4149 CBC         114 :         if (operand > bound1)
    4150 GIC           6 :             result = 0;
    4151 CBC         108 :         else if (operand <= bound2)
    4152 ECB             :         {
    4153 GIC          15 :             if (pg_add_s32_overflow(count, 1, &result))
    4154 CBC           3 :                 ereport(ERROR,
    4155                 :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    4156                 :                          errmsg("integer out of range")));
    4157                 :         }
    4158 ECB             :         else
    4159                 :         {
    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                 :         }
    4168 ECB             :     }
    4169                 :     else
    4170                 :     {
    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                 : 
    4177 GIC         405 :     PG_RETURN_INT32(result);
    4178                 : }
        

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