LCOV - code coverage report
Current view: top level - src/backend/utils/adt - numeric.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 2731 3148 86.8 %
Date: 2020-05-29 00:07:09 Functions: 172 187 92.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * numeric.c
       4             :  *    An exact numeric data type for the Postgres database system
       5             :  *
       6             :  * Original coding 1998, Jan Wieck.  Heavily revised 2003, Tom Lane.
       7             :  *
       8             :  * Many of the algorithmic ideas are borrowed from David M. Smith's "FM"
       9             :  * multiple-precision math library, most recently published as Algorithm
      10             :  * 786: Multiple-Precision Complex Arithmetic and Functions, ACM
      11             :  * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998,
      12             :  * pages 359-367.
      13             :  *
      14             :  * Copyright (c) 1998-2020, PostgreSQL Global Development Group
      15             :  *
      16             :  * IDENTIFICATION
      17             :  *    src/backend/utils/adt/numeric.c
      18             :  *
      19             :  *-------------------------------------------------------------------------
      20             :  */
      21             : 
      22             : #include "postgres.h"
      23             : 
      24             : #include <ctype.h>
      25             : #include <float.h>
      26             : #include <limits.h>
      27             : #include <math.h>
      28             : 
      29             : #include "catalog/pg_type.h"
      30             : #include "common/hashfn.h"
      31             : #include "common/int.h"
      32             : #include "funcapi.h"
      33             : #include "lib/hyperloglog.h"
      34             : #include "libpq/pqformat.h"
      35             : #include "miscadmin.h"
      36             : #include "nodes/nodeFuncs.h"
      37             : #include "nodes/supportnodes.h"
      38             : #include "utils/array.h"
      39             : #include "utils/builtins.h"
      40             : #include "utils/float.h"
      41             : #include "utils/guc.h"
      42             : #include "utils/int8.h"
      43             : #include "utils/numeric.h"
      44             : #include "utils/sortsupport.h"
      45             : 
      46             : /* ----------
      47             :  * Uncomment the following to enable compilation of dump_numeric()
      48             :  * and dump_var() and to get a dump of any result produced by make_result().
      49             :  * ----------
      50             : #define NUMERIC_DEBUG
      51             :  */
      52             : 
      53             : 
      54             : /* ----------
      55             :  * Local data types
      56             :  *
      57             :  * Numeric values are represented in a base-NBASE floating point format.
      58             :  * Each "digit" ranges from 0 to NBASE-1.  The type NumericDigit is signed
      59             :  * and wide enough to store a digit.  We assume that NBASE*NBASE can fit in
      60             :  * an int.  Although the purely calculational routines could handle any even
      61             :  * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
      62             :  * in NBASE a power of ten, so that I/O conversions and decimal rounding
      63             :  * are easy.  Also, it's actually more efficient if NBASE is rather less than
      64             :  * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var_fast to
      65             :  * postpone processing carries.
      66             :  *
      67             :  * Values of NBASE other than 10000 are considered of historical interest only
      68             :  * and are no longer supported in any sense; no mechanism exists for the client
      69             :  * to discover the base, so every client supporting binary mode expects the
      70             :  * base-10000 format.  If you plan to change this, also note the numeric
      71             :  * abbreviation code, which assumes NBASE=10000.
      72             :  * ----------
      73             :  */
      74             : 
      75             : #if 0
      76             : #define NBASE       10
      77             : #define HALF_NBASE  5
      78             : #define DEC_DIGITS  1           /* decimal digits per NBASE digit */
      79             : #define MUL_GUARD_DIGITS    4   /* these are measured in NBASE digits */
      80             : #define DIV_GUARD_DIGITS    8
      81             : 
      82             : typedef signed char NumericDigit;
      83             : #endif
      84             : 
      85             : #if 0
      86             : #define NBASE       100
      87             : #define HALF_NBASE  50
      88             : #define DEC_DIGITS  2           /* decimal digits per NBASE digit */
      89             : #define MUL_GUARD_DIGITS    3   /* these are measured in NBASE digits */
      90             : #define DIV_GUARD_DIGITS    6
      91             : 
      92             : typedef signed char NumericDigit;
      93             : #endif
      94             : 
      95             : #if 1
      96             : #define NBASE       10000
      97             : #define HALF_NBASE  5000
      98             : #define DEC_DIGITS  4           /* decimal digits per NBASE digit */
      99             : #define MUL_GUARD_DIGITS    2   /* these are measured in NBASE digits */
     100             : #define DIV_GUARD_DIGITS    4
     101             : 
     102             : typedef int16 NumericDigit;
     103             : #endif
     104             : 
     105             : /*
     106             :  * The Numeric type as stored on disk.
     107             :  *
     108             :  * If the high bits of the first word of a NumericChoice (n_header, or
     109             :  * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
     110             :  * numeric follows the NumericShort format; if they are NUMERIC_POS or
     111             :  * NUMERIC_NEG, it follows the NumericLong format.  If they are NUMERIC_NAN,
     112             :  * it is a NaN.  We currently always store a NaN using just two bytes (i.e.
     113             :  * only n_header), but previous releases used only the NumericLong format,
     114             :  * so we might find 4-byte NaNs on disk if a database has been migrated using
     115             :  * pg_upgrade.  In either case, when the high bits indicate a NaN, the
     116             :  * remaining bits are never examined.  Currently, we always initialize these
     117             :  * to zero, but it might be possible to use them for some other purpose in
     118             :  * the future.
     119             :  *
     120             :  * In the NumericShort format, the remaining 14 bits of the header word
     121             :  * (n_short.n_header) are allocated as follows: 1 for sign (positive or
     122             :  * negative), 6 for dynamic scale, and 7 for weight.  In practice, most
     123             :  * commonly-encountered values can be represented this way.
     124             :  *
     125             :  * In the NumericLong format, the remaining 14 bits of the header word
     126             :  * (n_long.n_sign_dscale) represent the display scale; and the weight is
     127             :  * stored separately in n_weight.
     128             :  *
     129             :  * NOTE: by convention, values in the packed form have been stripped of
     130             :  * all leading and trailing zero digits (where a "digit" is of base NBASE).
     131             :  * In particular, if the value is zero, there will be no digits at all!
     132             :  * The weight is arbitrary in that case, but we normally set it to zero.
     133             :  */
     134             : 
     135             : struct NumericShort
     136             : {
     137             :     uint16      n_header;       /* Sign + display scale + weight */
     138             :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
     139             : };
     140             : 
     141             : struct NumericLong
     142             : {
     143             :     uint16      n_sign_dscale;  /* Sign + display scale */
     144             :     int16       n_weight;       /* Weight of 1st digit  */
     145             :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
     146             : };
     147             : 
     148             : union NumericChoice
     149             : {
     150             :     uint16      n_header;       /* Header word */
     151             :     struct NumericLong n_long;  /* Long form (4-byte header) */
     152             :     struct NumericShort n_short;    /* Short form (2-byte header) */
     153             : };
     154             : 
     155             : struct NumericData
     156             : {
     157             :     int32       vl_len_;        /* varlena header (do not touch directly!) */
     158             :     union NumericChoice choice; /* choice of format */
     159             : };
     160             : 
     161             : 
     162             : /*
     163             :  * Interpretation of high bits.
     164             :  */
     165             : 
     166             : #define NUMERIC_SIGN_MASK   0xC000
     167             : #define NUMERIC_POS         0x0000
     168             : #define NUMERIC_NEG         0x4000
     169             : #define NUMERIC_SHORT       0x8000
     170             : #define NUMERIC_NAN         0xC000
     171             : 
     172             : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
     173             : #define NUMERIC_IS_NAN(n)       (NUMERIC_FLAGBITS(n) == NUMERIC_NAN)
     174             : #define NUMERIC_IS_SHORT(n)     (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
     175             : 
     176             : #define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
     177             : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
     178             : 
     179             : /*
     180             :  * If the flag bits are NUMERIC_SHORT or NUMERIC_NAN, we want the short header;
     181             :  * otherwise, we want the long one.  Instead of testing against each value, we
     182             :  * can just look at the high bit, for a slight efficiency gain.
     183             :  */
     184             : #define NUMERIC_HEADER_IS_SHORT(n)  (((n)->choice.n_header & 0x8000) != 0)
     185             : #define NUMERIC_HEADER_SIZE(n) \
     186             :     (VARHDRSZ + sizeof(uint16) + \
     187             :      (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
     188             : 
     189             : /*
     190             :  * Short format definitions.
     191             :  */
     192             : 
     193             : #define NUMERIC_SHORT_SIGN_MASK         0x2000
     194             : #define NUMERIC_SHORT_DSCALE_MASK       0x1F80
     195             : #define NUMERIC_SHORT_DSCALE_SHIFT      7
     196             : #define NUMERIC_SHORT_DSCALE_MAX        \
     197             :     (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
     198             : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK  0x0040
     199             : #define NUMERIC_SHORT_WEIGHT_MASK       0x003F
     200             : #define NUMERIC_SHORT_WEIGHT_MAX        NUMERIC_SHORT_WEIGHT_MASK
     201             : #define NUMERIC_SHORT_WEIGHT_MIN        (-(NUMERIC_SHORT_WEIGHT_MASK+1))
     202             : 
     203             : /*
     204             :  * Extract sign, display scale, weight.
     205             :  */
     206             : 
     207             : #define NUMERIC_DSCALE_MASK         0x3FFF
     208             : 
     209             : #define NUMERIC_SIGN(n) \
     210             :     (NUMERIC_IS_SHORT(n) ? \
     211             :         (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
     212             :         NUMERIC_NEG : NUMERIC_POS) : NUMERIC_FLAGBITS(n))
     213             : #define NUMERIC_DSCALE(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
     214             :     ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
     215             :         >> NUMERIC_SHORT_DSCALE_SHIFT \
     216             :     : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
     217             : #define NUMERIC_WEIGHT(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
     218             :     (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
     219             :         ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
     220             :      | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
     221             :     : ((n)->choice.n_long.n_weight))
     222             : 
     223             : /* ----------
     224             :  * NumericVar is the format we use for arithmetic.  The digit-array part
     225             :  * is the same as the NumericData storage format, but the header is more
     226             :  * complex.
     227             :  *
     228             :  * The value represented by a NumericVar is determined by the sign, weight,
     229             :  * ndigits, and digits[] array.
     230             :  *
     231             :  * Note: the first digit of a NumericVar's value is assumed to be multiplied
     232             :  * by NBASE ** weight.  Another way to say it is that there are weight+1
     233             :  * digits before the decimal point.  It is possible to have weight < 0.
     234             :  *
     235             :  * buf points at the physical start of the palloc'd digit buffer for the
     236             :  * NumericVar.  digits points at the first digit in actual use (the one
     237             :  * with the specified weight).  We normally leave an unused digit or two
     238             :  * (preset to zeroes) between buf and digits, so that there is room to store
     239             :  * a carry out of the top digit without reallocating space.  We just need to
     240             :  * decrement digits (and increment weight) to make room for the carry digit.
     241             :  * (There is no such extra space in a numeric value stored in the database,
     242             :  * only in a NumericVar in memory.)
     243             :  *
     244             :  * If buf is NULL then the digit buffer isn't actually palloc'd and should
     245             :  * not be freed --- see the constants below for an example.
     246             :  *
     247             :  * dscale, or display scale, is the nominal precision expressed as number
     248             :  * of digits after the decimal point (it must always be >= 0 at present).
     249             :  * dscale may be more than the number of physically stored fractional digits,
     250             :  * implying that we have suppressed storage of significant trailing zeroes.
     251             :  * It should never be less than the number of stored digits, since that would
     252             :  * imply hiding digits that are present.  NOTE that dscale is always expressed
     253             :  * in *decimal* digits, and so it may correspond to a fractional number of
     254             :  * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
     255             :  *
     256             :  * rscale, or result scale, is the target precision for a computation.
     257             :  * Like dscale it is expressed as number of *decimal* digits after the decimal
     258             :  * point, and is always >= 0 at present.
     259             :  * Note that rscale is not stored in variables --- it's figured on-the-fly
     260             :  * from the dscales of the inputs.
     261             :  *
     262             :  * While we consistently use "weight" to refer to the base-NBASE weight of
     263             :  * a numeric value, it is convenient in some scale-related calculations to
     264             :  * make use of the base-10 weight (ie, the approximate log10 of the value).
     265             :  * To avoid confusion, such a decimal-units weight is called a "dweight".
     266             :  *
     267             :  * NB: All the variable-level functions are written in a style that makes it
     268             :  * possible to give one and the same variable as argument and destination.
     269             :  * This is feasible because the digit buffer is separate from the variable.
     270             :  * ----------
     271             :  */
     272             : typedef struct NumericVar
     273             : {
     274             :     int         ndigits;        /* # of digits in digits[] - can be 0! */
     275             :     int         weight;         /* weight of first digit */
     276             :     int         sign;           /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
     277             :     int         dscale;         /* display scale */
     278             :     NumericDigit *buf;          /* start of palloc'd space for digits[] */
     279             :     NumericDigit *digits;       /* base-NBASE digits */
     280             : } NumericVar;
     281             : 
     282             : 
     283             : /* ----------
     284             :  * Data for generate_series
     285             :  * ----------
     286             :  */
     287             : typedef struct
     288             : {
     289             :     NumericVar  current;
     290             :     NumericVar  stop;
     291             :     NumericVar  step;
     292             : } generate_series_numeric_fctx;
     293             : 
     294             : 
     295             : /* ----------
     296             :  * Sort support.
     297             :  * ----------
     298             :  */
     299             : typedef struct
     300             : {
     301             :     void       *buf;            /* buffer for short varlenas */
     302             :     int64       input_count;    /* number of non-null values seen */
     303             :     bool        estimating;     /* true if estimating cardinality */
     304             : 
     305             :     hyperLogLogState abbr_card; /* cardinality estimator */
     306             : } NumericSortSupport;
     307             : 
     308             : 
     309             : /* ----------
     310             :  * Fast sum accumulator.
     311             :  *
     312             :  * NumericSumAccum is used to implement SUM(), and other standard aggregates
     313             :  * that track the sum of input values.  It uses 32-bit integers to store the
     314             :  * digits, instead of the normal 16-bit integers (with NBASE=10000).  This
     315             :  * way, we can safely accumulate up to NBASE - 1 values without propagating
     316             :  * carry, before risking overflow of any of the digits.  'num_uncarried'
     317             :  * tracks how many values have been accumulated without propagating carry.
     318             :  *
     319             :  * Positive and negative values are accumulated separately, in 'pos_digits'
     320             :  * and 'neg_digits'.  This is simpler and faster than deciding whether to add
     321             :  * or subtract from the current value, for each new value (see sub_var() for
     322             :  * the logic we avoid by doing this).  Both buffers are of same size, and
     323             :  * have the same weight and scale.  In accum_sum_final(), the positive and
     324             :  * negative sums are added together to produce the final result.
     325             :  *
     326             :  * When a new value has a larger ndigits or weight than the accumulator
     327             :  * currently does, the accumulator is enlarged to accommodate the new value.
     328             :  * We normally have one zero digit reserved for carry propagation, and that
     329             :  * is indicated by the 'have_carry_space' flag.  When accum_sum_carry() uses
     330             :  * up the reserved digit, it clears the 'have_carry_space' flag.  The next
     331             :  * call to accum_sum_add() will enlarge the buffer, to make room for the
     332             :  * extra digit, and set the flag again.
     333             :  *
     334             :  * To initialize a new accumulator, simply reset all fields to zeros.
     335             :  *
     336             :  * The accumulator does not handle NaNs.
     337             :  * ----------
     338             :  */
     339             : typedef struct NumericSumAccum
     340             : {
     341             :     int         ndigits;
     342             :     int         weight;
     343             :     int         dscale;
     344             :     int         num_uncarried;
     345             :     bool        have_carry_space;
     346             :     int32      *pos_digits;
     347             :     int32      *neg_digits;
     348             : } NumericSumAccum;
     349             : 
     350             : 
     351             : /*
     352             :  * We define our own macros for packing and unpacking abbreviated-key
     353             :  * representations for numeric values in order to avoid depending on
     354             :  * USE_FLOAT8_BYVAL.  The type of abbreviation we use is based only on
     355             :  * the size of a datum, not the argument-passing convention for float8.
     356             :  */
     357             : #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
     358             : #if SIZEOF_DATUM == 8
     359             : #define NumericAbbrevGetDatum(X) ((Datum) (X))
     360             : #define DatumGetNumericAbbrev(X) ((int64) (X))
     361             : #define NUMERIC_ABBREV_NAN       NumericAbbrevGetDatum(PG_INT64_MIN)
     362             : #else
     363             : #define NumericAbbrevGetDatum(X) ((Datum) (X))
     364             : #define DatumGetNumericAbbrev(X) ((int32) (X))
     365             : #define NUMERIC_ABBREV_NAN       NumericAbbrevGetDatum(PG_INT32_MIN)
     366             : #endif
     367             : 
     368             : 
     369             : /* ----------
     370             :  * Some preinitialized constants
     371             :  * ----------
     372             :  */
     373             : static const NumericDigit const_zero_data[1] = {0};
     374             : static const NumericVar const_zero =
     375             : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
     376             : 
     377             : static const NumericDigit const_one_data[1] = {1};
     378             : static const NumericVar const_one =
     379             : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
     380             : 
     381             : static const NumericDigit const_two_data[1] = {2};
     382             : static const NumericVar const_two =
     383             : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
     384             : 
     385             : #if DEC_DIGITS == 4 || DEC_DIGITS == 2
     386             : static const NumericDigit const_ten_data[1] = {10};
     387             : static const NumericVar const_ten =
     388             : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_ten_data};
     389             : #elif DEC_DIGITS == 1
     390             : static const NumericDigit const_ten_data[1] = {1};
     391             : static const NumericVar const_ten =
     392             : {1, 1, NUMERIC_POS, 0, NULL, (NumericDigit *) const_ten_data};
     393             : #endif
     394             : 
     395             : #if DEC_DIGITS == 4
     396             : static const NumericDigit const_zero_point_nine_data[1] = {9000};
     397             : #elif DEC_DIGITS == 2
     398             : static const NumericDigit const_zero_point_nine_data[1] = {90};
     399             : #elif DEC_DIGITS == 1
     400             : static const NumericDigit const_zero_point_nine_data[1] = {9};
     401             : #endif
     402             : static const NumericVar const_zero_point_nine =
     403             : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
     404             : 
     405             : #if DEC_DIGITS == 4
     406             : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
     407             : #elif DEC_DIGITS == 2
     408             : static const NumericDigit const_one_point_one_data[2] = {1, 10};
     409             : #elif DEC_DIGITS == 1
     410             : static const NumericDigit const_one_point_one_data[2] = {1, 1};
     411             : #endif
     412             : static const NumericVar const_one_point_one =
     413             : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
     414             : 
     415             : static const NumericVar const_nan =
     416             : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
     417             : 
     418             : #if DEC_DIGITS == 4
     419             : static const int round_powers[4] = {0, 1000, 100, 10};
     420             : #endif
     421             : 
     422             : 
     423             : /* ----------
     424             :  * Local functions
     425             :  * ----------
     426             :  */
     427             : 
     428             : #ifdef NUMERIC_DEBUG
     429             : static void dump_numeric(const char *str, Numeric num);
     430             : static void dump_var(const char *str, NumericVar *var);
     431             : #else
     432             : #define dump_numeric(s,n)
     433             : #define dump_var(s,v)
     434             : #endif
     435             : 
     436             : #define digitbuf_alloc(ndigits)  \
     437             :     ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
     438             : #define digitbuf_free(buf)  \
     439             :     do { \
     440             :          if ((buf) != NULL) \
     441             :              pfree(buf); \
     442             :     } while (0)
     443             : 
     444             : #define init_var(v)     MemSetAligned(v, 0, sizeof(NumericVar))
     445             : 
     446             : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
     447             :     (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
     448             : #define NUMERIC_NDIGITS(num) \
     449             :     ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
     450             : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
     451             :     ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
     452             :     (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
     453             :     (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
     454             : 
     455             : static void alloc_var(NumericVar *var, int ndigits);
     456             : static void free_var(NumericVar *var);
     457             : static void zero_var(NumericVar *var);
     458             : 
     459             : static const char *set_var_from_str(const char *str, const char *cp,
     460             :                                     NumericVar *dest);
     461             : static void set_var_from_num(Numeric value, NumericVar *dest);
     462             : static void init_var_from_num(Numeric num, NumericVar *dest);
     463             : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
     464             : static char *get_str_from_var(const NumericVar *var);
     465             : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
     466             : 
     467             : static Numeric make_result(const NumericVar *var);
     468             : static Numeric make_result_opt_error(const NumericVar *var, bool *error);
     469             : 
     470             : static void apply_typmod(NumericVar *var, int32 typmod);
     471             : 
     472             : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
     473             : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
     474             : static void int64_to_numericvar(int64 val, NumericVar *var);
     475             : #ifdef HAVE_INT128
     476             : static bool numericvar_to_int128(const NumericVar *var, int128 *result);
     477             : static void int128_to_numericvar(int128 val, NumericVar *var);
     478             : #endif
     479             : static double numeric_to_double_no_overflow(Numeric num);
     480             : static double numericvar_to_double_no_overflow(const NumericVar *var);
     481             : 
     482             : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
     483             : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
     484             : static int  numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
     485             : static int  numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
     486             : 
     487             : static Datum numeric_abbrev_convert_var(const NumericVar *var,
     488             :                                         NumericSortSupport *nss);
     489             : 
     490             : static int  cmp_numerics(Numeric num1, Numeric num2);
     491             : static int  cmp_var(const NumericVar *var1, const NumericVar *var2);
     492             : static int  cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
     493             :                            int var1weight, int var1sign,
     494             :                            const NumericDigit *var2digits, int var2ndigits,
     495             :                            int var2weight, int var2sign);
     496             : static void add_var(const NumericVar *var1, const NumericVar *var2,
     497             :                     NumericVar *result);
     498             : static void sub_var(const NumericVar *var1, const NumericVar *var2,
     499             :                     NumericVar *result);
     500             : static void mul_var(const NumericVar *var1, const NumericVar *var2,
     501             :                     NumericVar *result,
     502             :                     int rscale);
     503             : static void div_var(const NumericVar *var1, const NumericVar *var2,
     504             :                     NumericVar *result,
     505             :                     int rscale, bool round);
     506             : static void div_var_fast(const NumericVar *var1, const NumericVar *var2,
     507             :                          NumericVar *result, int rscale, bool round);
     508             : static int  select_div_scale(const NumericVar *var1, const NumericVar *var2);
     509             : static void mod_var(const NumericVar *var1, const NumericVar *var2,
     510             :                     NumericVar *result);
     511             : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
     512             :                         NumericVar *quot, NumericVar *rem);
     513             : static void ceil_var(const NumericVar *var, NumericVar *result);
     514             : static void floor_var(const NumericVar *var, NumericVar *result);
     515             : 
     516             : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
     517             :                     NumericVar *result);
     518             : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
     519             : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
     520             : static int  estimate_ln_dweight(const NumericVar *var);
     521             : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
     522             : static void log_var(const NumericVar *base, const NumericVar *num,
     523             :                     NumericVar *result);
     524             : static void power_var(const NumericVar *base, const NumericVar *exp,
     525             :                       NumericVar *result);
     526             : static void power_var_int(const NumericVar *base, int exp, NumericVar *result,
     527             :                           int rscale);
     528             : 
     529             : static int  cmp_abs(const NumericVar *var1, const NumericVar *var2);
     530             : static int  cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
     531             :                            int var1weight,
     532             :                            const NumericDigit *var2digits, int var2ndigits,
     533             :                            int var2weight);
     534             : static void add_abs(const NumericVar *var1, const NumericVar *var2,
     535             :                     NumericVar *result);
     536             : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
     537             :                     NumericVar *result);
     538             : static void round_var(NumericVar *var, int rscale);
     539             : static void trunc_var(NumericVar *var, int rscale);
     540             : static void strip_var(NumericVar *var);
     541             : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
     542             :                            const NumericVar *count_var, NumericVar *result_var);
     543             : 
     544             : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1);
     545             : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
     546             : static void accum_sum_carry(NumericSumAccum *accum);
     547             : static void accum_sum_reset(NumericSumAccum *accum);
     548             : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
     549             : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
     550             : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
     551             : 
     552             : 
     553             : /* ----------------------------------------------------------------------
     554             :  *
     555             :  * Input-, output- and rounding-functions
     556             :  *
     557             :  * ----------------------------------------------------------------------
     558             :  */
     559             : 
     560             : 
     561             : /*
     562             :  * numeric_in() -
     563             :  *
     564             :  *  Input function for numeric data type
     565             :  */
     566             : Datum
     567       27312 : numeric_in(PG_FUNCTION_ARGS)
     568             : {
     569       27312 :     char       *str = PG_GETARG_CSTRING(0);
     570             : 
     571             : #ifdef NOT_USED
     572             :     Oid         typelem = PG_GETARG_OID(1);
     573             : #endif
     574       27312 :     int32       typmod = PG_GETARG_INT32(2);
     575             :     Numeric     res;
     576             :     const char *cp;
     577             : 
     578             :     /* Skip leading spaces */
     579       27312 :     cp = str;
     580       27476 :     while (*cp)
     581             :     {
     582       27468 :         if (!isspace((unsigned char) *cp))
     583       27304 :             break;
     584         164 :         cp++;
     585             :     }
     586             : 
     587             :     /*
     588             :      * Check for NaN
     589             :      */
     590       27312 :     if (pg_strncasecmp(cp, "NaN", 3) == 0)
     591             :     {
     592         240 :         res = make_result(&const_nan);
     593             : 
     594             :         /* Should be nothing left but spaces */
     595         240 :         cp += 3;
     596         244 :         while (*cp)
     597             :         {
     598           4 :             if (!isspace((unsigned char) *cp))
     599           0 :                 ereport(ERROR,
     600             :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     601             :                          errmsg("invalid input syntax for type %s: \"%s\"",
     602             :                                 "numeric", str)));
     603           4 :             cp++;
     604             :         }
     605             :     }
     606             :     else
     607             :     {
     608             :         /*
     609             :          * Use set_var_from_str() to parse a normal numeric value
     610             :          */
     611             :         NumericVar  value;
     612             : 
     613      135360 :         init_var(&value);
     614             : 
     615       27072 :         cp = set_var_from_str(str, cp, &value);
     616             : 
     617             :         /*
     618             :          * We duplicate a few lines of code here because we would like to
     619             :          * throw any trailing-junk syntax error before any semantic error
     620             :          * resulting from apply_typmod.  We can't easily fold the two cases
     621             :          * together because we mustn't apply apply_typmod to a NaN.
     622             :          */
     623       27078 :         while (*cp)
     624             :         {
     625          48 :             if (!isspace((unsigned char) *cp))
     626          12 :                 ereport(ERROR,
     627             :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     628             :                          errmsg("invalid input syntax for type %s: \"%s\"",
     629             :                                 "numeric", str)));
     630          36 :             cp++;
     631             :         }
     632             : 
     633       27030 :         apply_typmod(&value, typmod);
     634             : 
     635       27030 :         res = make_result(&value);
     636       27030 :         free_var(&value);
     637             :     }
     638             : 
     639       27270 :     PG_RETURN_NUMERIC(res);
     640             : }
     641             : 
     642             : 
     643             : /*
     644             :  * numeric_out() -
     645             :  *
     646             :  *  Output function for numeric data type
     647             :  */
     648             : Datum
     649      465118 : numeric_out(PG_FUNCTION_ARGS)
     650             : {
     651      465118 :     Numeric     num = PG_GETARG_NUMERIC(0);
     652             :     NumericVar  x;
     653             :     char       *str;
     654             : 
     655             :     /*
     656             :      * Handle NaN
     657             :      */
     658      465118 :     if (NUMERIC_IS_NAN(num))
     659         260 :         PG_RETURN_CSTRING(pstrdup("NaN"));
     660             : 
     661             :     /*
     662             :      * Get the number in the variable format.
     663             :      */
     664      464858 :     init_var_from_num(num, &x);
     665             : 
     666      464858 :     str = get_str_from_var(&x);
     667             : 
     668      464858 :     PG_RETURN_CSTRING(str);
     669             : }
     670             : 
     671             : /*
     672             :  * numeric_is_nan() -
     673             :  *
     674             :  *  Is Numeric value a NaN?
     675             :  */
     676             : bool
     677       45770 : numeric_is_nan(Numeric num)
     678             : {
     679       45770 :     return NUMERIC_IS_NAN(num);
     680             : }
     681             : 
     682             : /*
     683             :  * numeric_maximum_size() -
     684             :  *
     685             :  *  Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
     686             :  */
     687             : int32
     688        5438 : numeric_maximum_size(int32 typmod)
     689             : {
     690             :     int         precision;
     691             :     int         numeric_digits;
     692             : 
     693        5438 :     if (typmod < (int32) (VARHDRSZ))
     694           0 :         return -1;
     695             : 
     696             :     /* precision (ie, max # of digits) is in upper bits of typmod */
     697        5438 :     precision = ((typmod - VARHDRSZ) >> 16) & 0xffff;
     698             : 
     699             :     /*
     700             :      * This formula computes the maximum number of NumericDigits we could need
     701             :      * in order to store the specified number of decimal digits. Because the
     702             :      * weight is stored as a number of NumericDigits rather than a number of
     703             :      * decimal digits, it's possible that the first NumericDigit will contain
     704             :      * only a single decimal digit.  Thus, the first two decimal digits can
     705             :      * require two NumericDigits to store, but it isn't until we reach
     706             :      * DEC_DIGITS + 2 decimal digits that we potentially need a third
     707             :      * NumericDigit.
     708             :      */
     709        5438 :     numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
     710             : 
     711             :     /*
     712             :      * In most cases, the size of a numeric will be smaller than the value
     713             :      * computed below, because the varlena header will typically get toasted
     714             :      * down to a single byte before being stored on disk, and it may also be
     715             :      * possible to use a short numeric header.  But our job here is to compute
     716             :      * the worst case.
     717             :      */
     718        5438 :     return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
     719             : }
     720             : 
     721             : /*
     722             :  * numeric_out_sci() -
     723             :  *
     724             :  *  Output function for numeric data type in scientific notation.
     725             :  */
     726             : char *
     727          40 : numeric_out_sci(Numeric num, int scale)
     728             : {
     729             :     NumericVar  x;
     730             :     char       *str;
     731             : 
     732             :     /*
     733             :      * Handle NaN
     734             :      */
     735          40 :     if (NUMERIC_IS_NAN(num))
     736           0 :         return pstrdup("NaN");
     737             : 
     738          40 :     init_var_from_num(num, &x);
     739             : 
     740          40 :     str = get_str_from_var_sci(&x, scale);
     741             : 
     742          40 :     return str;
     743             : }
     744             : 
     745             : /*
     746             :  * numeric_normalize() -
     747             :  *
     748             :  *  Output function for numeric data type, suppressing insignificant trailing
     749             :  *  zeroes and then any trailing decimal point.  The intent of this is to
     750             :  *  produce strings that are equal if and only if the input numeric values
     751             :  *  compare equal.
     752             :  */
     753             : char *
     754        6644 : numeric_normalize(Numeric num)
     755             : {
     756             :     NumericVar  x;
     757             :     char       *str;
     758             :     int         last;
     759             : 
     760             :     /*
     761             :      * Handle NaN
     762             :      */
     763        6644 :     if (NUMERIC_IS_NAN(num))
     764           0 :         return pstrdup("NaN");
     765             : 
     766        6644 :     init_var_from_num(num, &x);
     767             : 
     768        6644 :     str = get_str_from_var(&x);
     769             : 
     770             :     /* If there's no decimal point, there's certainly nothing to remove. */
     771        6644 :     if (strchr(str, '.') != NULL)
     772             :     {
     773             :         /*
     774             :          * Back up over trailing fractional zeroes.  Since there is a decimal
     775             :          * point, this loop will terminate safely.
     776             :          */
     777          28 :         last = strlen(str) - 1;
     778          56 :         while (str[last] == '0')
     779          28 :             last--;
     780             : 
     781             :         /* We want to get rid of the decimal point too, if it's now last. */
     782          28 :         if (str[last] == '.')
     783          28 :             last--;
     784             : 
     785             :         /* Delete whatever we backed up over. */
     786          28 :         str[last + 1] = '\0';
     787             :     }
     788             : 
     789        6644 :     return str;
     790             : }
     791             : 
     792             : /*
     793             :  *      numeric_recv            - converts external binary format to numeric
     794             :  *
     795             :  * External format is a sequence of int16's:
     796             :  * ndigits, weight, sign, dscale, NumericDigits.
     797             :  */
     798             : Datum
     799          16 : numeric_recv(PG_FUNCTION_ARGS)
     800             : {
     801          16 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     802             : 
     803             : #ifdef NOT_USED
     804             :     Oid         typelem = PG_GETARG_OID(1);
     805             : #endif
     806          16 :     int32       typmod = PG_GETARG_INT32(2);
     807             :     NumericVar  value;
     808             :     Numeric     res;
     809             :     int         len,
     810             :                 i;
     811             : 
     812          80 :     init_var(&value);
     813             : 
     814          16 :     len = (uint16) pq_getmsgint(buf, sizeof(uint16));
     815             : 
     816          16 :     alloc_var(&value, len);
     817             : 
     818          16 :     value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
     819             :     /* we allow any int16 for weight --- OK? */
     820             : 
     821          16 :     value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
     822          16 :     if (!(value.sign == NUMERIC_POS ||
     823           0 :           value.sign == NUMERIC_NEG ||
     824           0 :           value.sign == NUMERIC_NAN))
     825           0 :         ereport(ERROR,
     826             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     827             :                  errmsg("invalid sign in external \"numeric\" value")));
     828             : 
     829          16 :     value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
     830          16 :     if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
     831           0 :         ereport(ERROR,
     832             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     833             :                  errmsg("invalid scale in external \"numeric\" value")));
     834             : 
     835          52 :     for (i = 0; i < len; i++)
     836             :     {
     837          36 :         NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
     838             : 
     839          36 :         if (d < 0 || d >= NBASE)
     840           0 :             ereport(ERROR,
     841             :                     (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     842             :                      errmsg("invalid digit in external \"numeric\" value")));
     843          36 :         value.digits[i] = d;
     844             :     }
     845             : 
     846             :     /*
     847             :      * If the given dscale would hide any digits, truncate those digits away.
     848             :      * We could alternatively throw an error, but that would take a bunch of
     849             :      * extra code (about as much as trunc_var involves), and it might cause
     850             :      * client compatibility issues.
     851             :      */
     852          16 :     trunc_var(&value, value.dscale);
     853             : 
     854          16 :     apply_typmod(&value, typmod);
     855             : 
     856          16 :     res = make_result(&value);
     857          16 :     free_var(&value);
     858             : 
     859          16 :     PG_RETURN_NUMERIC(res);
     860             : }
     861             : 
     862             : /*
     863             :  *      numeric_send            - converts numeric to binary format
     864             :  */
     865             : Datum
     866          16 : numeric_send(PG_FUNCTION_ARGS)
     867             : {
     868          16 :     Numeric     num = PG_GETARG_NUMERIC(0);
     869             :     NumericVar  x;
     870             :     StringInfoData buf;
     871             :     int         i;
     872             : 
     873          16 :     init_var_from_num(num, &x);
     874             : 
     875          16 :     pq_begintypsend(&buf);
     876             : 
     877          16 :     pq_sendint16(&buf, x.ndigits);
     878          16 :     pq_sendint16(&buf, x.weight);
     879          16 :     pq_sendint16(&buf, x.sign);
     880          16 :     pq_sendint16(&buf, x.dscale);
     881          52 :     for (i = 0; i < x.ndigits; i++)
     882          36 :         pq_sendint16(&buf, x.digits[i]);
     883             : 
     884          16 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     885             : }
     886             : 
     887             : 
     888             : /*
     889             :  * numeric_support()
     890             :  *
     891             :  * Planner support function for the numeric() length coercion function.
     892             :  *
     893             :  * Flatten calls that solely represent increases in allowable precision.
     894             :  * Scale changes mutate every datum, so they are unoptimizable.  Some values,
     895             :  * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
     896             :  * an unconstrained numeric to any constrained numeric is also unoptimizable.
     897             :  */
     898             : Datum
     899         196 : numeric_support(PG_FUNCTION_ARGS)
     900             : {
     901         196 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     902         196 :     Node       *ret = NULL;
     903             : 
     904         196 :     if (IsA(rawreq, SupportRequestSimplify))
     905             :     {
     906          96 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
     907          96 :         FuncExpr   *expr = req->fcall;
     908             :         Node       *typmod;
     909             : 
     910             :         Assert(list_length(expr->args) >= 2);
     911             : 
     912          96 :         typmod = (Node *) lsecond(expr->args);
     913             : 
     914          96 :         if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
     915             :         {
     916          96 :             Node       *source = (Node *) linitial(expr->args);
     917          96 :             int32       old_typmod = exprTypmod(source);
     918          96 :             int32       new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
     919          96 :             int32       old_scale = (old_typmod - VARHDRSZ) & 0xffff;
     920          96 :             int32       new_scale = (new_typmod - VARHDRSZ) & 0xffff;
     921          96 :             int32       old_precision = (old_typmod - VARHDRSZ) >> 16 & 0xffff;
     922          96 :             int32       new_precision = (new_typmod - VARHDRSZ) >> 16 & 0xffff;
     923             : 
     924             :             /*
     925             :              * If new_typmod < VARHDRSZ, the destination is unconstrained;
     926             :              * that's always OK.  If old_typmod >= VARHDRSZ, the source is
     927             :              * constrained, and we're OK if the scale is unchanged and the
     928             :              * precision is not decreasing.  See further notes in function
     929             :              * header comment.
     930             :              */
     931          96 :             if (new_typmod < (int32) VARHDRSZ ||
     932           4 :                 (old_typmod >= (int32) VARHDRSZ &&
     933           4 :                  new_scale == old_scale && new_precision >= old_precision))
     934           4 :                 ret = relabel_to_typmod(source, new_typmod);
     935             :         }
     936             :     }
     937             : 
     938         196 :     PG_RETURN_POINTER(ret);
     939             : }
     940             : 
     941             : /*
     942             :  * numeric() -
     943             :  *
     944             :  *  This is a special function called by the Postgres database system
     945             :  *  before a value is stored in a tuple's attribute. The precision and
     946             :  *  scale of the attribute have to be applied on the value.
     947             :  */
     948             : Datum
     949        7264 : numeric     (PG_FUNCTION_ARGS)
     950             : {
     951        7264 :     Numeric     num = PG_GETARG_NUMERIC(0);
     952        7264 :     int32       typmod = PG_GETARG_INT32(1);
     953             :     Numeric     new;
     954             :     int32       tmp_typmod;
     955             :     int         precision;
     956             :     int         scale;
     957             :     int         ddigits;
     958             :     int         maxdigits;
     959             :     NumericVar  var;
     960             : 
     961             :     /*
     962             :      * Handle NaN
     963             :      */
     964        7264 :     if (NUMERIC_IS_NAN(num))
     965         104 :         PG_RETURN_NUMERIC(make_result(&const_nan));
     966             : 
     967             :     /*
     968             :      * If the value isn't a valid type modifier, simply return a copy of the
     969             :      * input value
     970             :      */
     971        7160 :     if (typmod < (int32) (VARHDRSZ))
     972             :     {
     973           0 :         new = (Numeric) palloc(VARSIZE(num));
     974           0 :         memcpy(new, num, VARSIZE(num));
     975           0 :         PG_RETURN_NUMERIC(new);
     976             :     }
     977             : 
     978             :     /*
     979             :      * Get the precision and scale out of the typmod value
     980             :      */
     981        7160 :     tmp_typmod = typmod - VARHDRSZ;
     982        7160 :     precision = (tmp_typmod >> 16) & 0xffff;
     983        7160 :     scale = tmp_typmod & 0xffff;
     984        7160 :     maxdigits = precision - scale;
     985             : 
     986             :     /*
     987             :      * If the number is certainly in bounds and due to the target scale no
     988             :      * rounding could be necessary, just make a copy of the input and modify
     989             :      * its scale fields, unless the larger scale forces us to abandon the
     990             :      * short representation.  (Note we assume the existing dscale is
     991             :      * honest...)
     992             :      */
     993        7160 :     ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
     994        7160 :     if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
     995        4320 :         && (NUMERIC_CAN_BE_SHORT(scale, NUMERIC_WEIGHT(num))
     996           0 :             || !NUMERIC_IS_SHORT(num)))
     997             :     {
     998        4320 :         new = (Numeric) palloc(VARSIZE(num));
     999        4320 :         memcpy(new, num, VARSIZE(num));
    1000        4320 :         if (NUMERIC_IS_SHORT(num))
    1001        4320 :             new->choice.n_short.n_header =
    1002        4320 :                 (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
    1003        4320 :                 | (scale << NUMERIC_SHORT_DSCALE_SHIFT);
    1004             :         else
    1005           0 :             new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
    1006           0 :                 ((uint16) scale & NUMERIC_DSCALE_MASK);
    1007        4320 :         PG_RETURN_NUMERIC(new);
    1008             :     }
    1009             : 
    1010             :     /*
    1011             :      * We really need to fiddle with things - unpack the number into a
    1012             :      * variable and let apply_typmod() do it.
    1013             :      */
    1014       14200 :     init_var(&var);
    1015             : 
    1016        2840 :     set_var_from_num(num, &var);
    1017        2840 :     apply_typmod(&var, typmod);
    1018        2820 :     new = make_result(&var);
    1019             : 
    1020        2820 :     free_var(&var);
    1021             : 
    1022        2820 :     PG_RETURN_NUMERIC(new);
    1023             : }
    1024             : 
    1025             : Datum
    1026        1518 : numerictypmodin(PG_FUNCTION_ARGS)
    1027             : {
    1028        1518 :     ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
    1029             :     int32      *tl;
    1030             :     int         n;
    1031             :     int32       typmod;
    1032             : 
    1033        1518 :     tl = ArrayGetIntegerTypmods(ta, &n);
    1034             : 
    1035        1518 :     if (n == 2)
    1036             :     {
    1037        1506 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
    1038           0 :             ereport(ERROR,
    1039             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1040             :                      errmsg("NUMERIC precision %d must be between 1 and %d",
    1041             :                             tl[0], NUMERIC_MAX_PRECISION)));
    1042        1506 :         if (tl[1] < 0 || tl[1] > tl[0])
    1043           0 :             ereport(ERROR,
    1044             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1045             :                      errmsg("NUMERIC scale %d must be between 0 and precision %d",
    1046             :                             tl[1], tl[0])));
    1047        1506 :         typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
    1048             :     }
    1049          12 :     else if (n == 1)
    1050             :     {
    1051           8 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
    1052           0 :             ereport(ERROR,
    1053             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1054             :                      errmsg("NUMERIC precision %d must be between 1 and %d",
    1055             :                             tl[0], NUMERIC_MAX_PRECISION)));
    1056             :         /* scale defaults to zero */
    1057           8 :         typmod = (tl[0] << 16) + VARHDRSZ;
    1058             :     }
    1059             :     else
    1060             :     {
    1061           4 :         ereport(ERROR,
    1062             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1063             :                  errmsg("invalid NUMERIC type modifier")));
    1064             :         typmod = 0;             /* keep compiler quiet */
    1065             :     }
    1066             : 
    1067        1514 :     PG_RETURN_INT32(typmod);
    1068             : }
    1069             : 
    1070             : Datum
    1071         148 : numerictypmodout(PG_FUNCTION_ARGS)
    1072             : {
    1073         148 :     int32       typmod = PG_GETARG_INT32(0);
    1074         148 :     char       *res = (char *) palloc(64);
    1075             : 
    1076         148 :     if (typmod >= 0)
    1077         296 :         snprintf(res, 64, "(%d,%d)",
    1078         148 :                  ((typmod - VARHDRSZ) >> 16) & 0xffff,
    1079         148 :                  (typmod - VARHDRSZ) & 0xffff);
    1080             :     else
    1081           0 :         *res = '\0';
    1082             : 
    1083         148 :     PG_RETURN_CSTRING(res);
    1084             : }
    1085             : 
    1086             : 
    1087             : /* ----------------------------------------------------------------------
    1088             :  *
    1089             :  * Sign manipulation, rounding and the like
    1090             :  *
    1091             :  * ----------------------------------------------------------------------
    1092             :  */
    1093             : 
    1094             : Datum
    1095         440 : numeric_abs(PG_FUNCTION_ARGS)
    1096             : {
    1097         440 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1098             :     Numeric     res;
    1099             : 
    1100             :     /*
    1101             :      * Handle NaN
    1102             :      */
    1103         440 :     if (NUMERIC_IS_NAN(num))
    1104           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1105             : 
    1106             :     /*
    1107             :      * Do it the easy way directly on the packed format
    1108             :      */
    1109         440 :     res = (Numeric) palloc(VARSIZE(num));
    1110         440 :     memcpy(res, num, VARSIZE(num));
    1111             : 
    1112         440 :     if (NUMERIC_IS_SHORT(num))
    1113         408 :         res->choice.n_short.n_header =
    1114         408 :             num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
    1115             :     else
    1116          32 :         res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
    1117             : 
    1118         440 :     PG_RETURN_NUMERIC(res);
    1119             : }
    1120             : 
    1121             : 
    1122             : Datum
    1123         410 : numeric_uminus(PG_FUNCTION_ARGS)
    1124             : {
    1125         410 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1126             :     Numeric     res;
    1127             : 
    1128             :     /*
    1129             :      * Handle NaN
    1130             :      */
    1131         410 :     if (NUMERIC_IS_NAN(num))
    1132          24 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1133             : 
    1134             :     /*
    1135             :      * Do it the easy way directly on the packed format
    1136             :      */
    1137         386 :     res = (Numeric) palloc(VARSIZE(num));
    1138         386 :     memcpy(res, num, VARSIZE(num));
    1139             : 
    1140             :     /*
    1141             :      * The packed format is known to be totally zero digit trimmed always. So
    1142             :      * we can identify a ZERO by the fact that there are no digits at all.  Do
    1143             :      * nothing to a zero.
    1144             :      */
    1145         386 :     if (NUMERIC_NDIGITS(num) != 0)
    1146             :     {
    1147             :         /* Else, flip the sign */
    1148         338 :         if (NUMERIC_IS_SHORT(num))
    1149         338 :             res->choice.n_short.n_header =
    1150         338 :                 num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
    1151           0 :         else if (NUMERIC_SIGN(num) == NUMERIC_POS)
    1152           0 :             res->choice.n_long.n_sign_dscale =
    1153           0 :                 NUMERIC_NEG | NUMERIC_DSCALE(num);
    1154             :         else
    1155           0 :             res->choice.n_long.n_sign_dscale =
    1156           0 :                 NUMERIC_POS | NUMERIC_DSCALE(num);
    1157             :     }
    1158             : 
    1159         386 :     PG_RETURN_NUMERIC(res);
    1160             : }
    1161             : 
    1162             : 
    1163             : Datum
    1164         164 : numeric_uplus(PG_FUNCTION_ARGS)
    1165             : {
    1166         164 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1167             :     Numeric     res;
    1168             : 
    1169         164 :     res = (Numeric) palloc(VARSIZE(num));
    1170         164 :     memcpy(res, num, VARSIZE(num));
    1171             : 
    1172         164 :     PG_RETURN_NUMERIC(res);
    1173             : }
    1174             : 
    1175             : /*
    1176             :  * numeric_sign() -
    1177             :  *
    1178             :  * returns -1 if the argument is less than 0, 0 if the argument is equal
    1179             :  * to 0, and 1 if the argument is greater than zero.
    1180             :  */
    1181             : Datum
    1182           0 : numeric_sign(PG_FUNCTION_ARGS)
    1183             : {
    1184           0 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1185             :     Numeric     res;
    1186             :     NumericVar  result;
    1187             : 
    1188             :     /*
    1189             :      * Handle NaN
    1190             :      */
    1191           0 :     if (NUMERIC_IS_NAN(num))
    1192           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1193             : 
    1194           0 :     init_var(&result);
    1195             : 
    1196             :     /*
    1197             :      * The packed format is known to be totally zero digit trimmed always. So
    1198             :      * we can identify a ZERO by the fact that there are no digits at all.
    1199             :      */
    1200           0 :     if (NUMERIC_NDIGITS(num) == 0)
    1201           0 :         set_var_from_var(&const_zero, &result);
    1202             :     else
    1203             :     {
    1204             :         /*
    1205             :          * And if there are some, we return a copy of ONE with the sign of our
    1206             :          * argument
    1207             :          */
    1208           0 :         set_var_from_var(&const_one, &result);
    1209           0 :         result.sign = NUMERIC_SIGN(num);
    1210             :     }
    1211             : 
    1212           0 :     res = make_result(&result);
    1213           0 :     free_var(&result);
    1214             : 
    1215           0 :     PG_RETURN_NUMERIC(res);
    1216             : }
    1217             : 
    1218             : 
    1219             : /*
    1220             :  * numeric_round() -
    1221             :  *
    1222             :  *  Round a value to have 'scale' digits after the decimal point.
    1223             :  *  We allow negative 'scale', implying rounding before the decimal
    1224             :  *  point --- Oracle interprets rounding that way.
    1225             :  */
    1226             : Datum
    1227        4346 : numeric_round(PG_FUNCTION_ARGS)
    1228             : {
    1229        4346 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1230        4346 :     int32       scale = PG_GETARG_INT32(1);
    1231             :     Numeric     res;
    1232             :     NumericVar  arg;
    1233             : 
    1234             :     /*
    1235             :      * Handle NaN
    1236             :      */
    1237        4346 :     if (NUMERIC_IS_NAN(num))
    1238           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1239             : 
    1240             :     /*
    1241             :      * Limit the scale value to avoid possible overflow in calculations
    1242             :      */
    1243        4346 :     scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
    1244        4346 :     scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
    1245             : 
    1246             :     /*
    1247             :      * Unpack the argument and round it at the proper digit position
    1248             :      */
    1249       21730 :     init_var(&arg);
    1250        4346 :     set_var_from_num(num, &arg);
    1251             : 
    1252        4346 :     round_var(&arg, scale);
    1253             : 
    1254             :     /* We don't allow negative output dscale */
    1255        4346 :     if (scale < 0)
    1256         120 :         arg.dscale = 0;
    1257             : 
    1258             :     /*
    1259             :      * Return the rounded result
    1260             :      */
    1261        4346 :     res = make_result(&arg);
    1262             : 
    1263        4346 :     free_var(&arg);
    1264        4346 :     PG_RETURN_NUMERIC(res);
    1265             : }
    1266             : 
    1267             : 
    1268             : /*
    1269             :  * numeric_trunc() -
    1270             :  *
    1271             :  *  Truncate a value to have 'scale' digits after the decimal point.
    1272             :  *  We allow negative 'scale', implying a truncation before the decimal
    1273             :  *  point --- Oracle interprets truncation that way.
    1274             :  */
    1275             : Datum
    1276         192 : numeric_trunc(PG_FUNCTION_ARGS)
    1277             : {
    1278         192 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1279         192 :     int32       scale = PG_GETARG_INT32(1);
    1280             :     Numeric     res;
    1281             :     NumericVar  arg;
    1282             : 
    1283             :     /*
    1284             :      * Handle NaN
    1285             :      */
    1286         192 :     if (NUMERIC_IS_NAN(num))
    1287           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1288             : 
    1289             :     /*
    1290             :      * Limit the scale value to avoid possible overflow in calculations
    1291             :      */
    1292         192 :     scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
    1293         192 :     scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
    1294             : 
    1295             :     /*
    1296             :      * Unpack the argument and truncate it at the proper digit position
    1297             :      */
    1298         960 :     init_var(&arg);
    1299         192 :     set_var_from_num(num, &arg);
    1300             : 
    1301         192 :     trunc_var(&arg, scale);
    1302             : 
    1303             :     /* We don't allow negative output dscale */
    1304         192 :     if (scale < 0)
    1305           0 :         arg.dscale = 0;
    1306             : 
    1307             :     /*
    1308             :      * Return the truncated result
    1309             :      */
    1310         192 :     res = make_result(&arg);
    1311             : 
    1312         192 :     free_var(&arg);
    1313         192 :     PG_RETURN_NUMERIC(res);
    1314             : }
    1315             : 
    1316             : 
    1317             : /*
    1318             :  * numeric_ceil() -
    1319             :  *
    1320             :  *  Return the smallest integer greater than or equal to the argument
    1321             :  */
    1322             : Datum
    1323         116 : numeric_ceil(PG_FUNCTION_ARGS)
    1324             : {
    1325         116 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1326             :     Numeric     res;
    1327             :     NumericVar  result;
    1328             : 
    1329         116 :     if (NUMERIC_IS_NAN(num))
    1330           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1331             : 
    1332         116 :     init_var_from_num(num, &result);
    1333         116 :     ceil_var(&result, &result);
    1334             : 
    1335         116 :     res = make_result(&result);
    1336         116 :     free_var(&result);
    1337             : 
    1338         116 :     PG_RETURN_NUMERIC(res);
    1339             : }
    1340             : 
    1341             : 
    1342             : /*
    1343             :  * numeric_floor() -
    1344             :  *
    1345             :  *  Return the largest integer equal to or less than the argument
    1346             :  */
    1347             : Datum
    1348          52 : numeric_floor(PG_FUNCTION_ARGS)
    1349             : {
    1350          52 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1351             :     Numeric     res;
    1352             :     NumericVar  result;
    1353             : 
    1354          52 :     if (NUMERIC_IS_NAN(num))
    1355           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1356             : 
    1357          52 :     init_var_from_num(num, &result);
    1358          52 :     floor_var(&result, &result);
    1359             : 
    1360          52 :     res = make_result(&result);
    1361          52 :     free_var(&result);
    1362             : 
    1363          52 :     PG_RETURN_NUMERIC(res);
    1364             : }
    1365             : 
    1366             : 
    1367             : /*
    1368             :  * generate_series_numeric() -
    1369             :  *
    1370             :  *  Generate series of numeric.
    1371             :  */
    1372             : Datum
    1373         144 : generate_series_numeric(PG_FUNCTION_ARGS)
    1374             : {
    1375         144 :     return generate_series_step_numeric(fcinfo);
    1376             : }
    1377             : 
    1378             : Datum
    1379         268 : generate_series_step_numeric(PG_FUNCTION_ARGS)
    1380             : {
    1381             :     generate_series_numeric_fctx *fctx;
    1382             :     FuncCallContext *funcctx;
    1383             :     MemoryContext oldcontext;
    1384             : 
    1385         268 :     if (SRF_IS_FIRSTCALL())
    1386             :     {
    1387          80 :         Numeric     start_num = PG_GETARG_NUMERIC(0);
    1388          80 :         Numeric     stop_num = PG_GETARG_NUMERIC(1);
    1389          80 :         NumericVar  steploc = const_one;
    1390             : 
    1391             :         /* handle NaN in start and stop values */
    1392          80 :         if (NUMERIC_IS_NAN(start_num))
    1393           4 :             ereport(ERROR,
    1394             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1395             :                      errmsg("start value cannot be NaN")));
    1396             : 
    1397          76 :         if (NUMERIC_IS_NAN(stop_num))
    1398           4 :             ereport(ERROR,
    1399             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1400             :                      errmsg("stop value cannot be NaN")));
    1401             : 
    1402             :         /* see if we were given an explicit step size */
    1403          72 :         if (PG_NARGS() == 3)
    1404             :         {
    1405          32 :             Numeric     step_num = PG_GETARG_NUMERIC(2);
    1406             : 
    1407          32 :             if (NUMERIC_IS_NAN(step_num))
    1408           4 :                 ereport(ERROR,
    1409             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1410             :                          errmsg("step size cannot be NaN")));
    1411             : 
    1412          28 :             init_var_from_num(step_num, &steploc);
    1413             : 
    1414          28 :             if (cmp_var(&steploc, &const_zero) == 0)
    1415           4 :                 ereport(ERROR,
    1416             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1417             :                          errmsg("step size cannot equal zero")));
    1418             :         }
    1419             : 
    1420             :         /* create a function context for cross-call persistence */
    1421          64 :         funcctx = SRF_FIRSTCALL_INIT();
    1422             : 
    1423             :         /*
    1424             :          * Switch to memory context appropriate for multiple function calls.
    1425             :          */
    1426          64 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1427             : 
    1428             :         /* allocate memory for user context */
    1429             :         fctx = (generate_series_numeric_fctx *)
    1430          64 :             palloc(sizeof(generate_series_numeric_fctx));
    1431             : 
    1432             :         /*
    1433             :          * Use fctx to keep state from call to call. Seed current with the
    1434             :          * original start value. We must copy the start_num and stop_num
    1435             :          * values rather than pointing to them, since we may have detoasted
    1436             :          * them in the per-call context.
    1437             :          */
    1438         320 :         init_var(&fctx->current);
    1439         320 :         init_var(&fctx->stop);
    1440         320 :         init_var(&fctx->step);
    1441             : 
    1442          64 :         set_var_from_num(start_num, &fctx->current);
    1443          64 :         set_var_from_num(stop_num, &fctx->stop);
    1444          64 :         set_var_from_var(&steploc, &fctx->step);
    1445             : 
    1446          64 :         funcctx->user_fctx = fctx;
    1447          64 :         MemoryContextSwitchTo(oldcontext);
    1448             :     }
    1449             : 
    1450             :     /* stuff done on every call of the function */
    1451         252 :     funcctx = SRF_PERCALL_SETUP();
    1452             : 
    1453             :     /*
    1454             :      * Get the saved state and use current state as the result of this
    1455             :      * iteration.
    1456             :      */
    1457         252 :     fctx = funcctx->user_fctx;
    1458             : 
    1459         488 :     if ((fctx->step.sign == NUMERIC_POS &&
    1460         236 :          cmp_var(&fctx->current, &fctx->stop) <= 0) ||
    1461          92 :         (fctx->step.sign == NUMERIC_NEG &&
    1462          16 :          cmp_var(&fctx->current, &fctx->stop) >= 0))
    1463             :     {
    1464         188 :         Numeric     result = make_result(&fctx->current);
    1465             : 
    1466             :         /* switch to memory context appropriate for iteration calculation */
    1467         188 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1468             : 
    1469             :         /* increment current in preparation for next iteration */
    1470         188 :         add_var(&fctx->current, &fctx->step, &fctx->current);
    1471         188 :         MemoryContextSwitchTo(oldcontext);
    1472             : 
    1473             :         /* do when there is more left to send */
    1474         188 :         SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
    1475             :     }
    1476             :     else
    1477             :         /* do when there is no more left */
    1478          64 :         SRF_RETURN_DONE(funcctx);
    1479             : }
    1480             : 
    1481             : 
    1482             : /*
    1483             :  * Implements the numeric version of the width_bucket() function
    1484             :  * defined by SQL2003. See also width_bucket_float8().
    1485             :  *
    1486             :  * 'bound1' and 'bound2' are the lower and upper bounds of the
    1487             :  * histogram's range, respectively. 'count' is the number of buckets
    1488             :  * in the histogram. width_bucket() returns an integer indicating the
    1489             :  * bucket number that 'operand' belongs to in an equiwidth histogram
    1490             :  * with the specified characteristics. An operand smaller than the
    1491             :  * lower bound is assigned to bucket 0. An operand greater than the
    1492             :  * upper bound is assigned to an additional bucket (with number
    1493             :  * count+1). We don't allow "NaN" for any of the numeric arguments.
    1494             :  */
    1495             : Datum
    1496         396 : width_bucket_numeric(PG_FUNCTION_ARGS)
    1497             : {
    1498         396 :     Numeric     operand = PG_GETARG_NUMERIC(0);
    1499         396 :     Numeric     bound1 = PG_GETARG_NUMERIC(1);
    1500         396 :     Numeric     bound2 = PG_GETARG_NUMERIC(2);
    1501         396 :     int32       count = PG_GETARG_INT32(3);
    1502             :     NumericVar  count_var;
    1503             :     NumericVar  result_var;
    1504             :     int32       result;
    1505             : 
    1506         396 :     if (count <= 0)
    1507           8 :         ereport(ERROR,
    1508             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1509             :                  errmsg("count must be greater than zero")));
    1510             : 
    1511         388 :     if (NUMERIC_IS_NAN(operand) ||
    1512         384 :         NUMERIC_IS_NAN(bound1) ||
    1513         384 :         NUMERIC_IS_NAN(bound2))
    1514           4 :         ereport(ERROR,
    1515             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1516             :                  errmsg("operand, lower bound, and upper bound cannot be NaN")));
    1517             : 
    1518        1920 :     init_var(&result_var);
    1519        1920 :     init_var(&count_var);
    1520             : 
    1521             :     /* Convert 'count' to a numeric, for ease of use later */
    1522         384 :     int64_to_numericvar((int64) count, &count_var);
    1523             : 
    1524         384 :     switch (cmp_numerics(bound1, bound2))
    1525             :     {
    1526           4 :         case 0:
    1527           4 :             ereport(ERROR,
    1528             :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1529             :                      errmsg("lower bound cannot equal upper bound")));
    1530             :             break;
    1531             : 
    1532             :             /* bound1 < bound2 */
    1533         304 :         case -1:
    1534         304 :             if (cmp_numerics(operand, bound1) < 0)
    1535          68 :                 set_var_from_var(&const_zero, &result_var);
    1536         236 :             else if (cmp_numerics(operand, bound2) >= 0)
    1537          60 :                 add_var(&count_var, &const_one, &result_var);
    1538             :             else
    1539         176 :                 compute_bucket(operand, bound1, bound2,
    1540             :                                &count_var, &result_var);
    1541         304 :             break;
    1542             : 
    1543             :             /* bound1 > bound2 */
    1544          76 :         case 1:
    1545          76 :             if (cmp_numerics(operand, bound1) > 0)
    1546           4 :                 set_var_from_var(&const_zero, &result_var);
    1547          72 :             else if (cmp_numerics(operand, bound2) <= 0)
    1548           8 :                 add_var(&count_var, &const_one, &result_var);
    1549             :             else
    1550          64 :                 compute_bucket(operand, bound1, bound2,
    1551             :                                &count_var, &result_var);
    1552          76 :             break;
    1553             :     }
    1554             : 
    1555             :     /* if result exceeds the range of a legal int4, we ereport here */
    1556         380 :     if (!numericvar_to_int32(&result_var, &result))
    1557           0 :         ereport(ERROR,
    1558             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1559             :                  errmsg("integer out of range")));
    1560             : 
    1561         380 :     free_var(&count_var);
    1562         380 :     free_var(&result_var);
    1563             : 
    1564         380 :     PG_RETURN_INT32(result);
    1565             : }
    1566             : 
    1567             : /*
    1568             :  * If 'operand' is not outside the bucket range, determine the correct
    1569             :  * bucket for it to go. The calculations performed by this function
    1570             :  * are derived directly from the SQL2003 spec.
    1571             :  */
    1572             : static void
    1573         240 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
    1574             :                const NumericVar *count_var, NumericVar *result_var)
    1575             : {
    1576             :     NumericVar  bound1_var;
    1577             :     NumericVar  bound2_var;
    1578             :     NumericVar  operand_var;
    1579             : 
    1580         240 :     init_var_from_num(bound1, &bound1_var);
    1581         240 :     init_var_from_num(bound2, &bound2_var);
    1582         240 :     init_var_from_num(operand, &operand_var);
    1583             : 
    1584         240 :     if (cmp_var(&bound1_var, &bound2_var) < 0)
    1585             :     {
    1586         176 :         sub_var(&operand_var, &bound1_var, &operand_var);
    1587         176 :         sub_var(&bound2_var, &bound1_var, &bound2_var);
    1588         176 :         div_var(&operand_var, &bound2_var, result_var,
    1589             :                 select_div_scale(&operand_var, &bound2_var), true);
    1590             :     }
    1591             :     else
    1592             :     {
    1593          64 :         sub_var(&bound1_var, &operand_var, &operand_var);
    1594          64 :         sub_var(&bound1_var, &bound2_var, &bound1_var);
    1595          64 :         div_var(&operand_var, &bound1_var, result_var,
    1596             :                 select_div_scale(&operand_var, &bound1_var), true);
    1597             :     }
    1598             : 
    1599         240 :     mul_var(result_var, count_var, result_var,
    1600         240 :             result_var->dscale + count_var->dscale);
    1601         240 :     add_var(result_var, &const_one, result_var);
    1602         240 :     floor_var(result_var, result_var);
    1603             : 
    1604         240 :     free_var(&bound1_var);
    1605         240 :     free_var(&bound2_var);
    1606         240 :     free_var(&operand_var);
    1607         240 : }
    1608             : 
    1609             : /* ----------------------------------------------------------------------
    1610             :  *
    1611             :  * Comparison functions
    1612             :  *
    1613             :  * Note: btree indexes need these routines not to leak memory; therefore,
    1614             :  * be careful to free working copies of toasted datums.  Most places don't
    1615             :  * need to be so careful.
    1616             :  *
    1617             :  * Sort support:
    1618             :  *
    1619             :  * We implement the sortsupport strategy routine in order to get the benefit of
    1620             :  * abbreviation. The ordinary numeric comparison can be quite slow as a result
    1621             :  * of palloc/pfree cycles (due to detoasting packed values for alignment);
    1622             :  * while this could be worked on itself, the abbreviation strategy gives more
    1623             :  * speedup in many common cases.
    1624             :  *
    1625             :  * Two different representations are used for the abbreviated form, one in
    1626             :  * int32 and one in int64, whichever fits into a by-value Datum.  In both cases
    1627             :  * the representation is negated relative to the original value, because we use
    1628             :  * the largest negative value for NaN, which sorts higher than other values. We
    1629             :  * convert the absolute value of the numeric to a 31-bit or 63-bit positive
    1630             :  * value, and then negate it if the original number was positive.
    1631             :  *
    1632             :  * We abort the abbreviation process if the abbreviation cardinality is below
    1633             :  * 0.01% of the row count (1 per 10k non-null rows).  The actual break-even
    1634             :  * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
    1635             :  * very small penalty), but we don't want to build up too many abbreviated
    1636             :  * values before first testing for abort, so we take the slightly pessimistic
    1637             :  * number.  We make no attempt to estimate the cardinality of the real values,
    1638             :  * since it plays no part in the cost model here (if the abbreviation is equal,
    1639             :  * the cost of comparing equal and unequal underlying values is comparable).
    1640             :  * We discontinue even checking for abort (saving us the hashing overhead) if
    1641             :  * the estimated cardinality gets to 100k; that would be enough to support many
    1642             :  * billions of rows while doing no worse than breaking even.
    1643             :  *
    1644             :  * ----------------------------------------------------------------------
    1645             :  */
    1646             : 
    1647             : /*
    1648             :  * Sort support strategy routine.
    1649             :  */
    1650             : Datum
    1651         666 : numeric_sortsupport(PG_FUNCTION_ARGS)
    1652             : {
    1653         666 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
    1654             : 
    1655         666 :     ssup->comparator = numeric_fast_cmp;
    1656             : 
    1657         666 :     if (ssup->abbreviate)
    1658             :     {
    1659             :         NumericSortSupport *nss;
    1660         132 :         MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
    1661             : 
    1662         132 :         nss = palloc(sizeof(NumericSortSupport));
    1663             : 
    1664             :         /*
    1665             :          * palloc a buffer for handling unaligned packed values in addition to
    1666             :          * the support struct
    1667             :          */
    1668         132 :         nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
    1669             : 
    1670         132 :         nss->input_count = 0;
    1671         132 :         nss->estimating = true;
    1672         132 :         initHyperLogLog(&nss->abbr_card, 10);
    1673             : 
    1674         132 :         ssup->ssup_extra = nss;
    1675             : 
    1676         132 :         ssup->abbrev_full_comparator = ssup->comparator;
    1677         132 :         ssup->comparator = numeric_cmp_abbrev;
    1678         132 :         ssup->abbrev_converter = numeric_abbrev_convert;
    1679         132 :         ssup->abbrev_abort = numeric_abbrev_abort;
    1680             : 
    1681         132 :         MemoryContextSwitchTo(oldcontext);
    1682             :     }
    1683             : 
    1684         666 :     PG_RETURN_VOID();
    1685             : }
    1686             : 
    1687             : /*
    1688             :  * Abbreviate a numeric datum, handling NaNs and detoasting
    1689             :  * (must not leak memory!)
    1690             :  */
    1691             : static Datum
    1692         326 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
    1693             : {
    1694         326 :     NumericSortSupport *nss = ssup->ssup_extra;
    1695         326 :     void       *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
    1696             :     Numeric     value;
    1697             :     Datum       result;
    1698             : 
    1699         326 :     nss->input_count += 1;
    1700             : 
    1701             :     /*
    1702             :      * This is to handle packed datums without needing a palloc/pfree cycle;
    1703             :      * we keep and reuse a buffer large enough to handle any short datum.
    1704             :      */
    1705         326 :     if (VARATT_IS_SHORT(original_varatt))
    1706             :     {
    1707         326 :         void       *buf = nss->buf;
    1708         326 :         Size        sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
    1709             : 
    1710             :         Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
    1711             : 
    1712         326 :         SET_VARSIZE(buf, VARHDRSZ + sz);
    1713         326 :         memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
    1714             : 
    1715         326 :         value = (Numeric) buf;
    1716             :     }
    1717             :     else
    1718           0 :         value = (Numeric) original_varatt;
    1719             : 
    1720         326 :     if (NUMERIC_IS_NAN(value))
    1721             :     {
    1722          12 :         result = NUMERIC_ABBREV_NAN;
    1723             :     }
    1724             :     else
    1725             :     {
    1726             :         NumericVar  var;
    1727             : 
    1728         314 :         init_var_from_num(value, &var);
    1729             : 
    1730         314 :         result = numeric_abbrev_convert_var(&var, nss);
    1731             :     }
    1732             : 
    1733             :     /* should happen only for external/compressed toasts */
    1734         326 :     if ((Pointer) original_varatt != DatumGetPointer(original_datum))
    1735           0 :         pfree(original_varatt);
    1736             : 
    1737         326 :     return result;
    1738             : }
    1739             : 
    1740             : /*
    1741             :  * Consider whether to abort abbreviation.
    1742             :  *
    1743             :  * We pay no attention to the cardinality of the non-abbreviated data. There is
    1744             :  * no reason to do so: unlike text, we have no fast check for equal values, so
    1745             :  * we pay the full overhead whenever the abbreviations are equal regardless of
    1746             :  * whether the underlying values are also equal.
    1747             :  */
    1748             : static bool
    1749           0 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
    1750             : {
    1751           0 :     NumericSortSupport *nss = ssup->ssup_extra;
    1752             :     double      abbr_card;
    1753             : 
    1754           0 :     if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
    1755           0 :         return false;
    1756             : 
    1757           0 :     abbr_card = estimateHyperLogLog(&nss->abbr_card);
    1758             : 
    1759             :     /*
    1760             :      * If we have >100k distinct values, then even if we were sorting many
    1761             :      * billion rows we'd likely still break even, and the penalty of undoing
    1762             :      * that many rows of abbrevs would probably not be worth it. Stop even
    1763             :      * counting at that point.
    1764             :      */
    1765           0 :     if (abbr_card > 100000.0)
    1766             :     {
    1767             : #ifdef TRACE_SORT
    1768           0 :         if (trace_sort)
    1769           0 :             elog(LOG,
    1770             :                  "numeric_abbrev: estimation ends at cardinality %f"
    1771             :                  " after " INT64_FORMAT " values (%d rows)",
    1772             :                  abbr_card, nss->input_count, memtupcount);
    1773             : #endif
    1774           0 :         nss->estimating = false;
    1775           0 :         return false;
    1776             :     }
    1777             : 
    1778             :     /*
    1779             :      * Target minimum cardinality is 1 per ~10k of non-null inputs.  (The
    1780             :      * break even point is somewhere between one per 100k rows, where
    1781             :      * abbreviation has a very slight penalty, and 1 per 10k where it wins by
    1782             :      * a measurable percentage.)  We use the relatively pessimistic 10k
    1783             :      * threshold, and add a 0.5 row fudge factor, because it allows us to
    1784             :      * abort earlier on genuinely pathological data where we've had exactly
    1785             :      * one abbreviated value in the first 10k (non-null) rows.
    1786             :      */
    1787           0 :     if (abbr_card < nss->input_count / 10000.0 + 0.5)
    1788             :     {
    1789             : #ifdef TRACE_SORT
    1790           0 :         if (trace_sort)
    1791           0 :             elog(LOG,
    1792             :                  "numeric_abbrev: aborting abbreviation at cardinality %f"
    1793             :                  " below threshold %f after " INT64_FORMAT " values (%d rows)",
    1794             :                  abbr_card, nss->input_count / 10000.0 + 0.5,
    1795             :                  nss->input_count, memtupcount);
    1796             : #endif
    1797           0 :         return true;
    1798             :     }
    1799             : 
    1800             : #ifdef TRACE_SORT
    1801           0 :     if (trace_sort)
    1802           0 :         elog(LOG,
    1803             :              "numeric_abbrev: cardinality %f"
    1804             :              " after " INT64_FORMAT " values (%d rows)",
    1805             :              abbr_card, nss->input_count, memtupcount);
    1806             : #endif
    1807             : 
    1808           0 :     return false;
    1809             : }
    1810             : 
    1811             : /*
    1812             :  * Non-fmgr interface to the comparison routine to allow sortsupport to elide
    1813             :  * the fmgr call.  The saving here is small given how slow numeric comparisons
    1814             :  * are, but it is a required part of the sort support API when abbreviations
    1815             :  * are performed.
    1816             :  *
    1817             :  * Two palloc/pfree cycles could be saved here by using persistent buffers for
    1818             :  * aligning short-varlena inputs, but this has not so far been considered to
    1819             :  * be worth the effort.
    1820             :  */
    1821             : static int
    1822     2541484 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
    1823             : {
    1824     2541484 :     Numeric     nx = DatumGetNumeric(x);
    1825     2541484 :     Numeric     ny = DatumGetNumeric(y);
    1826             :     int         result;
    1827             : 
    1828     2541484 :     result = cmp_numerics(nx, ny);
    1829             : 
    1830     2541484 :     if ((Pointer) nx != DatumGetPointer(x))
    1831      115008 :         pfree(nx);
    1832     2541484 :     if ((Pointer) ny != DatumGetPointer(y))
    1833      115008 :         pfree(ny);
    1834             : 
    1835     2541484 :     return result;
    1836             : }
    1837             : 
    1838             : /*
    1839             :  * Compare abbreviations of values. (Abbreviations may be equal where the true
    1840             :  * values differ, but if the abbreviations differ, they must reflect the
    1841             :  * ordering of the true values.)
    1842             :  */
    1843             : static int
    1844         248 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
    1845             : {
    1846             :     /*
    1847             :      * NOTE WELL: this is intentionally backwards, because the abbreviation is
    1848             :      * negated relative to the original value, to handle NaN.
    1849             :      */
    1850         248 :     if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
    1851           8 :         return 1;
    1852         240 :     if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
    1853         236 :         return -1;
    1854           4 :     return 0;
    1855             : }
    1856             : 
    1857             : /*
    1858             :  * Abbreviate a NumericVar according to the available bit size.
    1859             :  *
    1860             :  * The 31-bit value is constructed as:
    1861             :  *
    1862             :  *  0 + 7bits digit weight + 24 bits digit value
    1863             :  *
    1864             :  * where the digit weight is in single decimal digits, not digit words, and
    1865             :  * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
    1866             :  * significant decimal digits of the value converted to binary. Values whose
    1867             :  * weights would fall outside the representable range are rounded off to zero
    1868             :  * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
    1869             :  * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
    1870             :  * where values are outside the range 10^-44 to 10^83, which is not considered
    1871             :  * to be a serious limitation, or when values are of the same magnitude and
    1872             :  * equal in the first 7 decimal digits, which is considered to be an
    1873             :  * unavoidable limitation given the available bits. (Stealing three more bits
    1874             :  * to compare another digit would narrow the range of representable weights by
    1875             :  * a factor of 8, which starts to look like a real limiting factor.)
    1876             :  *
    1877             :  * (The value 44 for the excess is essentially arbitrary)
    1878             :  *
    1879             :  * The 63-bit value is constructed as:
    1880             :  *
    1881             :  *  0 + 7bits weight + 4 x 14-bit packed digit words
    1882             :  *
    1883             :  * The weight in this case is again stored in excess-44, but this time it is
    1884             :  * the original weight in digit words (i.e. powers of 10000). The first four
    1885             :  * digit words of the value (if present; trailing zeros are assumed as needed)
    1886             :  * are packed into 14 bits each to form the rest of the value. Again,
    1887             :  * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
    1888             :  * representable range in this case is 10^-176 to 10^332, which is considered
    1889             :  * to be good enough for all practical purposes, and comparison of 4 words
    1890             :  * means that at least 13 decimal digits are compared, which is considered to
    1891             :  * be a reasonable compromise between effectiveness and efficiency in computing
    1892             :  * the abbreviation.
    1893             :  *
    1894             :  * (The value 44 for the excess is even more arbitrary here, it was chosen just
    1895             :  * to match the value used in the 31-bit case)
    1896             :  *
    1897             :  * [1] - Excess-k representation means that the value is offset by adding 'k'
    1898             :  * and then treated as unsigned, so the smallest representable value is stored
    1899             :  * with all bits zero. This allows simple comparisons to work on the composite
    1900             :  * value.
    1901             :  */
    1902             : 
    1903             : #if NUMERIC_ABBREV_BITS == 64
    1904             : 
    1905             : static Datum
    1906         314 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
    1907             : {
    1908         314 :     int         ndigits = var->ndigits;
    1909         314 :     int         weight = var->weight;
    1910             :     int64       result;
    1911             : 
    1912         314 :     if (ndigits == 0 || weight < -44)
    1913             :     {
    1914          16 :         result = 0;
    1915             :     }
    1916         298 :     else if (weight > 83)
    1917             :     {
    1918           0 :         result = PG_INT64_MAX;
    1919             :     }
    1920             :     else
    1921             :     {
    1922         298 :         result = ((int64) (weight + 44) << 56);
    1923             : 
    1924         298 :         switch (ndigits)
    1925             :         {
    1926           0 :             default:
    1927           0 :                 result |= ((int64) var->digits[3]);
    1928             :                 /* FALLTHROUGH */
    1929           4 :             case 3:
    1930           4 :                 result |= ((int64) var->digits[2]) << 14;
    1931             :                 /* FALLTHROUGH */
    1932          68 :             case 2:
    1933          68 :                 result |= ((int64) var->digits[1]) << 28;
    1934             :                 /* FALLTHROUGH */
    1935         298 :             case 1:
    1936         298 :                 result |= ((int64) var->digits[0]) << 42;
    1937         298 :                 break;
    1938             :         }
    1939             :     }
    1940             : 
    1941             :     /* the abbrev is negated relative to the original */
    1942         314 :     if (var->sign == NUMERIC_POS)
    1943         270 :         result = -result;
    1944             : 
    1945         314 :     if (nss->estimating)
    1946             :     {
    1947         628 :         uint32      tmp = ((uint32) result
    1948         314 :                            ^ (uint32) ((uint64) result >> 32));
    1949             : 
    1950         314 :         addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
    1951             :     }
    1952             : 
    1953         314 :     return NumericAbbrevGetDatum(result);
    1954             : }
    1955             : 
    1956             : #endif                          /* NUMERIC_ABBREV_BITS == 64 */
    1957             : 
    1958             : #if NUMERIC_ABBREV_BITS == 32
    1959             : 
    1960             : static Datum
    1961             : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
    1962             : {
    1963             :     int         ndigits = var->ndigits;
    1964             :     int         weight = var->weight;
    1965             :     int32       result;
    1966             : 
    1967             :     if (ndigits == 0 || weight < -11)
    1968             :     {
    1969             :         result = 0;
    1970             :     }
    1971             :     else if (weight > 20)
    1972             :     {
    1973             :         result = PG_INT32_MAX;
    1974             :     }
    1975             :     else
    1976             :     {
    1977             :         NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
    1978             : 
    1979             :         weight = (weight + 11) * 4;
    1980             : 
    1981             :         result = var->digits[0];
    1982             : 
    1983             :         /*
    1984             :          * "result" now has 1 to 4 nonzero decimal digits. We pack in more
    1985             :          * digits to make 7 in total (largest we can fit in 24 bits)
    1986             :          */
    1987             : 
    1988             :         if (result > 999)
    1989             :         {
    1990             :             /* already have 4 digits, add 3 more */
    1991             :             result = (result * 1000) + (nxt1 / 10);
    1992             :             weight += 3;
    1993             :         }
    1994             :         else if (result > 99)
    1995             :         {
    1996             :             /* already have 3 digits, add 4 more */
    1997             :             result = (result * 10000) + nxt1;
    1998             :             weight += 2;
    1999             :         }
    2000             :         else if (result > 9)
    2001             :         {
    2002             :             NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
    2003             : 
    2004             :             /* already have 2 digits, add 5 more */
    2005             :             result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
    2006             :             weight += 1;
    2007             :         }
    2008             :         else
    2009             :         {
    2010             :             NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
    2011             : 
    2012             :             /* already have 1 digit, add 6 more */
    2013             :             result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
    2014             :         }
    2015             : 
    2016             :         result = result | (weight << 24);
    2017             :     }
    2018             : 
    2019             :     /* the abbrev is negated relative to the original */
    2020             :     if (var->sign == NUMERIC_POS)
    2021             :         result = -result;
    2022             : 
    2023             :     if (nss->estimating)
    2024             :     {
    2025             :         uint32      tmp = (uint32) result;
    2026             : 
    2027             :         addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
    2028             :     }
    2029             : 
    2030             :     return NumericAbbrevGetDatum(result);
    2031             : }
    2032             : 
    2033             : #endif                          /* NUMERIC_ABBREV_BITS == 32 */
    2034             : 
    2035             : /*
    2036             :  * Ordinary (non-sortsupport) comparisons follow.
    2037             :  */
    2038             : 
    2039             : Datum
    2040      831938 : numeric_cmp(PG_FUNCTION_ARGS)
    2041             : {
    2042      831938 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2043      831938 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2044             :     int         result;
    2045             : 
    2046      831938 :     result = cmp_numerics(num1, num2);
    2047             : 
    2048      831938 :     PG_FREE_IF_COPY(num1, 0);
    2049      831938 :     PG_FREE_IF_COPY(num2, 1);
    2050             : 
    2051      831938 :     PG_RETURN_INT32(result);
    2052             : }
    2053             : 
    2054             : 
    2055             : Datum
    2056      167506 : numeric_eq(PG_FUNCTION_ARGS)
    2057             : {
    2058      167506 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2059      167506 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2060             :     bool        result;
    2061             : 
    2062      167506 :     result = cmp_numerics(num1, num2) == 0;
    2063             : 
    2064      167506 :     PG_FREE_IF_COPY(num1, 0);
    2065      167506 :     PG_FREE_IF_COPY(num2, 1);
    2066             : 
    2067      167506 :     PG_RETURN_BOOL(result);
    2068             : }
    2069             : 
    2070             : Datum
    2071        3376 : numeric_ne(PG_FUNCTION_ARGS)
    2072             : {
    2073        3376 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2074        3376 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2075             :     bool        result;
    2076             : 
    2077        3376 :     result = cmp_numerics(num1, num2) != 0;
    2078             : 
    2079        3376 :     PG_FREE_IF_COPY(num1, 0);
    2080        3376 :     PG_FREE_IF_COPY(num2, 1);
    2081             : 
    2082        3376 :     PG_RETURN_BOOL(result);
    2083             : }
    2084             : 
    2085             : Datum
    2086       27030 : numeric_gt(PG_FUNCTION_ARGS)
    2087             : {
    2088       27030 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2089       27030 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2090             :     bool        result;
    2091             : 
    2092       27030 :     result = cmp_numerics(num1, num2) > 0;
    2093             : 
    2094       27030 :     PG_FREE_IF_COPY(num1, 0);
    2095       27030 :     PG_FREE_IF_COPY(num2, 1);
    2096             : 
    2097       27030 :     PG_RETURN_BOOL(result);
    2098             : }
    2099             : 
    2100             : Datum
    2101       14386 : numeric_ge(PG_FUNCTION_ARGS)
    2102             : {
    2103       14386 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2104       14386 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2105             :     bool        result;
    2106             : 
    2107       14386 :     result = cmp_numerics(num1, num2) >= 0;
    2108             : 
    2109       14386 :     PG_FREE_IF_COPY(num1, 0);
    2110       14386 :     PG_FREE_IF_COPY(num2, 1);
    2111             : 
    2112       14386 :     PG_RETURN_BOOL(result);
    2113             : }
    2114             : 
    2115             : Datum
    2116       14730 : numeric_lt(PG_FUNCTION_ARGS)
    2117             : {
    2118       14730 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2119       14730 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2120             :     bool        result;
    2121             : 
    2122       14730 :     result = cmp_numerics(num1, num2) < 0;
    2123             : 
    2124       14730 :     PG_FREE_IF_COPY(num1, 0);
    2125       14730 :     PG_FREE_IF_COPY(num2, 1);
    2126             : 
    2127       14730 :     PG_RETURN_BOOL(result);
    2128             : }
    2129             : 
    2130             : Datum
    2131       13284 : numeric_le(PG_FUNCTION_ARGS)
    2132             : {
    2133       13284 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2134       13284 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2135             :     bool        result;
    2136             : 
    2137       13284 :     result = cmp_numerics(num1, num2) <= 0;
    2138             : 
    2139       13284 :     PG_FREE_IF_COPY(num1, 0);
    2140       13284 :     PG_FREE_IF_COPY(num2, 1);
    2141             : 
    2142       13284 :     PG_RETURN_BOOL(result);
    2143             : }
    2144             : 
    2145             : static int
    2146     3614878 : cmp_numerics(Numeric num1, Numeric num2)
    2147             : {
    2148             :     int         result;
    2149             : 
    2150             :     /*
    2151             :      * We consider all NANs to be equal and larger than any non-NAN. This is
    2152             :      * somewhat arbitrary; the important thing is to have a consistent sort
    2153             :      * order.
    2154             :      */
    2155     3614878 :     if (NUMERIC_IS_NAN(num1))
    2156             :     {
    2157        9964 :         if (NUMERIC_IS_NAN(num2))
    2158        1688 :             result = 0;         /* NAN = NAN */
    2159             :         else
    2160        8276 :             result = 1;         /* NAN > non-NAN */
    2161             :     }
    2162     3604914 :     else if (NUMERIC_IS_NAN(num2))
    2163             :     {
    2164       11322 :         result = -1;            /* non-NAN < NAN */
    2165             :     }
    2166             :     else
    2167             :     {
    2168     7187184 :         result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
    2169     3593592 :                                 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
    2170     3593592 :                                 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
    2171     3593592 :                                 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
    2172             :     }
    2173             : 
    2174     3614878 :     return result;
    2175             : }
    2176             : 
    2177             : /*
    2178             :  * in_range support function for numeric.
    2179             :  */
    2180             : Datum
    2181         312 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
    2182             : {
    2183         312 :     Numeric     val = PG_GETARG_NUMERIC(0);
    2184         312 :     Numeric     base = PG_GETARG_NUMERIC(1);
    2185         312 :     Numeric     offset = PG_GETARG_NUMERIC(2);
    2186         312 :     bool        sub = PG_GETARG_BOOL(3);
    2187         312 :     bool        less = PG_GETARG_BOOL(4);
    2188             :     bool        result;
    2189             : 
    2190             :     /*
    2191             :      * Reject negative or NaN offset.  Negative is per spec, and NaN is
    2192             :      * because appropriate semantics for that seem non-obvious.
    2193             :      */
    2194         312 :     if (NUMERIC_IS_NAN(offset) || NUMERIC_SIGN(offset) == NUMERIC_NEG)
    2195           4 :         ereport(ERROR,
    2196             :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
    2197             :                  errmsg("invalid preceding or following size in window function")));
    2198             : 
    2199             :     /*
    2200             :      * Deal with cases where val and/or base is NaN, following the rule that
    2201             :      * NaN sorts after non-NaN (cf cmp_numerics).  The offset cannot affect
    2202             :      * the conclusion.
    2203             :      */
    2204         308 :     if (NUMERIC_IS_NAN(val))
    2205             :     {
    2206          24 :         if (NUMERIC_IS_NAN(base))
    2207          16 :             result = true;      /* NAN = NAN */
    2208             :         else
    2209           8 :             result = !less;     /* NAN > non-NAN */
    2210             :     }
    2211         284 :     else if (NUMERIC_IS_NAN(base))
    2212             :     {
    2213           8 :         result = less;          /* non-NAN < NAN */
    2214             :     }
    2215             :     else
    2216             :     {
    2217             :         /*
    2218             :          * Otherwise go ahead and compute base +/- offset.  While it's
    2219             :          * possible for this to overflow the numeric format, it's unlikely
    2220             :          * enough that we don't take measures to prevent it.
    2221             :          */
    2222             :         NumericVar  valv;
    2223             :         NumericVar  basev;
    2224             :         NumericVar  offsetv;
    2225             :         NumericVar  sum;
    2226             : 
    2227         276 :         init_var_from_num(val, &valv);
    2228         276 :         init_var_from_num(base, &basev);
    2229         276 :         init_var_from_num(offset, &offsetv);
    2230        1380 :         init_var(&sum);
    2231             : 
    2232         276 :         if (sub)
    2233         140 :             sub_var(&basev, &offsetv, &sum);
    2234             :         else
    2235         136 :             add_var(&basev, &offsetv, &sum);
    2236             : 
    2237         276 :         if (less)
    2238         136 :             result = (cmp_var(&valv, &sum) <= 0);
    2239             :         else
    2240         140 :             result = (cmp_var(&valv, &sum) >= 0);
    2241             : 
    2242         276 :         free_var(&sum);
    2243             :     }
    2244             : 
    2245         308 :     PG_FREE_IF_COPY(val, 0);
    2246         308 :     PG_FREE_IF_COPY(base, 1);
    2247         308 :     PG_FREE_IF_COPY(offset, 2);
    2248             : 
    2249         308 :     PG_RETURN_BOOL(result);
    2250             : }
    2251             : 
    2252             : Datum
    2253      442852 : hash_numeric(PG_FUNCTION_ARGS)
    2254             : {
    2255      442852 :     Numeric     key = PG_GETARG_NUMERIC(0);
    2256             :     Datum       digit_hash;
    2257             :     Datum       result;
    2258             :     int         weight;
    2259             :     int         start_offset;
    2260             :     int         end_offset;
    2261             :     int         i;
    2262             :     int         hash_len;
    2263             :     NumericDigit *digits;
    2264             : 
    2265             :     /* If it's NaN, don't try to hash the rest of the fields */
    2266      442852 :     if (NUMERIC_IS_NAN(key))
    2267           0 :         PG_RETURN_UINT32(0);
    2268             : 
    2269      442852 :     weight = NUMERIC_WEIGHT(key);
    2270      442852 :     start_offset = 0;
    2271      442852 :     end_offset = 0;
    2272             : 
    2273             :     /*
    2274             :      * Omit any leading or trailing zeros from the input to the hash. The
    2275             :      * numeric implementation *should* guarantee that leading and trailing
    2276             :      * zeros are suppressed, but we're paranoid. Note that we measure the
    2277             :      * starting and ending offsets in units of NumericDigits, not bytes.
    2278             :      */
    2279      442852 :     digits = NUMERIC_DIGITS(key);
    2280      442852 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
    2281             :     {
    2282      441182 :         if (digits[i] != (NumericDigit) 0)
    2283      441182 :             break;
    2284             : 
    2285           0 :         start_offset++;
    2286             : 
    2287             :         /*
    2288             :          * The weight is effectively the # of digits before the decimal point,
    2289             :          * so decrement it for each leading zero we skip.
    2290             :          */
    2291           0 :         weight--;
    2292             :     }
    2293             : 
    2294             :     /*
    2295             :      * If there are no non-zero digits, then the value of the number is zero,
    2296             :      * regardless of any other fields.
    2297             :      */
    2298      442852 :     if (NUMERIC_NDIGITS(key) == start_offset)
    2299        1670 :         PG_RETURN_UINT32(-1);
    2300             : 
    2301      441182 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
    2302             :     {
    2303      441182 :         if (digits[i] != (NumericDigit) 0)
    2304      441182 :             break;
    2305             : 
    2306           0 :         end_offset++;
    2307             :     }
    2308             : 
    2309             :     /* If we get here, there should be at least one non-zero digit */
    2310             :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
    2311             : 
    2312             :     /*
    2313             :      * Note that we don't hash on the Numeric's scale, since two numerics can
    2314             :      * compare equal but have different scales. We also don't hash on the
    2315             :      * sign, although we could: since a sign difference implies inequality,
    2316             :      * this shouldn't affect correctness.
    2317             :      */
    2318      441182 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
    2319      441182 :     digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
    2320             :                           hash_len * sizeof(NumericDigit));
    2321             : 
    2322             :     /* Mix in the weight, via XOR */
    2323      441182 :     result = digit_hash ^ weight;
    2324             : 
    2325      441182 :     PG_RETURN_DATUM(result);
    2326             : }
    2327             : 
    2328             : /*
    2329             :  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
    2330             :  * Otherwise, similar to hash_numeric.
    2331             :  */
    2332             : Datum
    2333          56 : hash_numeric_extended(PG_FUNCTION_ARGS)
    2334             : {
    2335          56 :     Numeric     key = PG_GETARG_NUMERIC(0);
    2336          56 :     uint64      seed = PG_GETARG_INT64(1);
    2337             :     Datum       digit_hash;
    2338             :     Datum       result;
    2339             :     int         weight;
    2340             :     int         start_offset;
    2341             :     int         end_offset;
    2342             :     int         i;
    2343             :     int         hash_len;
    2344             :     NumericDigit *digits;
    2345             : 
    2346          56 :     if (NUMERIC_IS_NAN(key))
    2347           0 :         PG_RETURN_UINT64(seed);
    2348             : 
    2349          56 :     weight = NUMERIC_WEIGHT(key);
    2350          56 :     start_offset = 0;
    2351          56 :     end_offset = 0;
    2352             : 
    2353          56 :     digits = NUMERIC_DIGITS(key);
    2354          56 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
    2355             :     {
    2356          48 :         if (digits[i] != (NumericDigit) 0)
    2357          48 :             break;
    2358             : 
    2359           0 :         start_offset++;
    2360             : 
    2361           0 :         weight--;
    2362             :     }
    2363             : 
    2364          56 :     if (NUMERIC_NDIGITS(key) == start_offset)
    2365           8 :         PG_RETURN_UINT64(seed - 1);
    2366             : 
    2367          48 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
    2368             :     {
    2369          48 :         if (digits[i] != (NumericDigit) 0)
    2370          48 :             break;
    2371             : 
    2372           0 :         end_offset++;
    2373             :     }
    2374             : 
    2375             :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
    2376             : 
    2377          48 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
    2378          48 :     digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
    2379          48 :                                                       + start_offset),
    2380             :                                    hash_len * sizeof(NumericDigit),
    2381             :                                    seed);
    2382             : 
    2383          48 :     result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
    2384             : 
    2385          48 :     PG_RETURN_DATUM(result);
    2386             : }
    2387             : 
    2388             : 
    2389             : /* ----------------------------------------------------------------------
    2390             :  *
    2391             :  * Basic arithmetic functions
    2392             :  *
    2393             :  * ----------------------------------------------------------------------
    2394             :  */
    2395             : 
    2396             : 
    2397             : /*
    2398             :  * numeric_add() -
    2399             :  *
    2400             :  *  Add two numerics
    2401             :  */
    2402             : Datum
    2403        1574 : numeric_add(PG_FUNCTION_ARGS)
    2404             : {
    2405        1574 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2406        1574 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2407             :     Numeric     res;
    2408             : 
    2409        1574 :     res = numeric_add_opt_error(num1, num2, NULL);
    2410             : 
    2411        1574 :     PG_RETURN_NUMERIC(res);
    2412             : }
    2413             : 
    2414             : /*
    2415             :  * numeric_add_opt_error() -
    2416             :  *
    2417             :  *  Internal version of numeric_add().  If "*have_error" flag is provided,
    2418             :  *  on error it's set to true, NULL returned.  This is helpful when caller
    2419             :  *  need to handle errors by itself.
    2420             :  */
    2421             : Numeric
    2422        1626 : numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
    2423             : {
    2424             :     NumericVar  arg1;
    2425             :     NumericVar  arg2;
    2426             :     NumericVar  result;
    2427             :     Numeric     res;
    2428             : 
    2429             :     /*
    2430             :      * Handle NaN
    2431             :      */
    2432        1626 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2433           0 :         return make_result(&const_nan);
    2434             : 
    2435             :     /*
    2436             :      * Unpack the values, let add_var() compute the result and return it.
    2437             :      */
    2438        1626 :     init_var_from_num(num1, &arg1);
    2439        1626 :     init_var_from_num(num2, &arg2);
    2440             : 
    2441        8130 :     init_var(&result);
    2442        1626 :     add_var(&arg1, &arg2, &result);
    2443             : 
    2444        1626 :     res = make_result_opt_error(&result, have_error);
    2445             : 
    2446        1626 :     free_var(&result);
    2447             : 
    2448        1626 :     return res;
    2449             : }
    2450             : 
    2451             : 
    2452             : /*
    2453             :  * numeric_sub() -
    2454             :  *
    2455             :  *  Subtract one numeric from another
    2456             :  */
    2457             : Datum
    2458       38412 : numeric_sub(PG_FUNCTION_ARGS)
    2459             : {
    2460       38412 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2461       38412 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2462             :     Numeric     res;
    2463             : 
    2464       38412 :     res = numeric_sub_opt_error(num1, num2, NULL);
    2465             : 
    2466       38412 :     PG_RETURN_NUMERIC(res);
    2467             : }
    2468             : 
    2469             : 
    2470             : /*
    2471             :  * numeric_sub_opt_error() -
    2472             :  *
    2473             :  *  Internal version of numeric_sub().  If "*have_error" flag is provided,
    2474             :  *  on error it's set to true, NULL returned.  This is helpful when caller
    2475             :  *  need to handle errors by itself.
    2476             :  */
    2477             : Numeric
    2478       38440 : numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
    2479             : {
    2480             :     NumericVar  arg1;
    2481             :     NumericVar  arg2;
    2482             :     NumericVar  result;
    2483             :     Numeric     res;
    2484             : 
    2485             :     /*
    2486             :      * Handle NaN
    2487             :      */
    2488       38440 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2489        2356 :         return make_result(&const_nan);
    2490             : 
    2491             :     /*
    2492             :      * Unpack the values, let sub_var() compute the result and return it.
    2493             :      */
    2494       36084 :     init_var_from_num(num1, &arg1);
    2495       36084 :     init_var_from_num(num2, &arg2);
    2496             : 
    2497      180420 :     init_var(&result);
    2498       36084 :     sub_var(&arg1, &arg2, &result);
    2499             : 
    2500       36084 :     res = make_result_opt_error(&result, have_error);
    2501             : 
    2502       36084 :     free_var(&result);
    2503             : 
    2504       36084 :     return res;
    2505             : }
    2506             : 
    2507             : 
    2508             : /*
    2509             :  * numeric_mul() -
    2510             :  *
    2511             :  *  Calculate the product of two numerics
    2512             :  */
    2513             : Datum
    2514      323912 : numeric_mul(PG_FUNCTION_ARGS)
    2515             : {
    2516      323912 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2517      323912 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2518             :     Numeric     res;
    2519             : 
    2520      323912 :     res = numeric_mul_opt_error(num1, num2, NULL);
    2521             : 
    2522      323912 :     PG_RETURN_NUMERIC(res);
    2523             : }
    2524             : 
    2525             : 
    2526             : /*
    2527             :  * numeric_mul_opt_error() -
    2528             :  *
    2529             :  *  Internal version of numeric_mul().  If "*have_error" flag is provided,
    2530             :  *  on error it's set to true, NULL returned.  This is helpful when caller
    2531             :  *  need to handle errors by itself.
    2532             :  */
    2533             : Numeric
    2534      323920 : numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
    2535             : {
    2536             :     NumericVar  arg1;
    2537             :     NumericVar  arg2;
    2538             :     NumericVar  result;
    2539             :     Numeric     res;
    2540             : 
    2541             :     /*
    2542             :      * Handle NaN
    2543             :      */
    2544      323920 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2545           0 :         return make_result(&const_nan);
    2546             : 
    2547             :     /*
    2548             :      * Unpack the values, let mul_var() compute the result and return it.
    2549             :      * Unlike add_var() and sub_var(), mul_var() will round its result. In the
    2550             :      * case of numeric_mul(), which is invoked for the * operator on numerics,
    2551             :      * we request exact representation for the product (rscale = sum(dscale of
    2552             :      * arg1, dscale of arg2)).
    2553             :      */
    2554      323920 :     init_var_from_num(num1, &arg1);
    2555      323920 :     init_var_from_num(num2, &arg2);
    2556             : 
    2557     1619600 :     init_var(&result);
    2558      323920 :     mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
    2559             : 
    2560      323920 :     res = make_result_opt_error(&result, have_error);
    2561             : 
    2562      323920 :     free_var(&result);
    2563             : 
    2564      323920 :     return res;
    2565             : }
    2566             : 
    2567             : 
    2568             : /*
    2569             :  * numeric_div() -
    2570             :  *
    2571             :  *  Divide one numeric into another
    2572             :  */
    2573             : Datum
    2574       72540 : numeric_div(PG_FUNCTION_ARGS)
    2575             : {
    2576       72540 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2577       72540 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2578             :     Numeric     res;
    2579             : 
    2580       72540 :     res = numeric_div_opt_error(num1, num2, NULL);
    2581             : 
    2582       72532 :     PG_RETURN_NUMERIC(res);
    2583             : }
    2584             : 
    2585             : 
    2586             : /*
    2587             :  * numeric_div_opt_error() -
    2588             :  *
    2589             :  *  Internal version of numeric_div().  If "*have_error" flag is provided,
    2590             :  *  on error it's set to true, NULL returned.  This is helpful when caller
    2591             :  *  need to handle errors by itself.
    2592             :  */
    2593             : Numeric
    2594       72584 : numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
    2595             : {
    2596             :     NumericVar  arg1;
    2597             :     NumericVar  arg2;
    2598             :     NumericVar  result;
    2599             :     Numeric     res;
    2600             :     int         rscale;
    2601             : 
    2602       72584 :     if (have_error)
    2603          32 :         *have_error = false;
    2604             : 
    2605             :     /*
    2606             :      * Handle NaN
    2607             :      */
    2608       72584 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2609           0 :         return make_result(&const_nan);
    2610             : 
    2611             :     /*
    2612             :      * Unpack the arguments
    2613             :      */
    2614       72584 :     init_var_from_num(num1, &arg1);
    2615       72584 :     init_var_from_num(num2, &arg2);
    2616             : 
    2617      362920 :     init_var(&result);
    2618             : 
    2619             :     /*
    2620             :      * Select scale for division result
    2621             :      */
    2622       72584 :     rscale = select_div_scale(&arg1, &arg2);
    2623             : 
    2624             :     /*
    2625             :      * If "have_error" is provided, check for division by zero here
    2626             :      */
    2627       72584 :     if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
    2628             :     {
    2629           8 :         *have_error = true;
    2630           8 :         return NULL;
    2631             :     }
    2632             : 
    2633             :     /*
    2634             :      * Do the divide and return the result
    2635             :      */
    2636       72576 :     div_var(&arg1, &arg2, &result, rscale, true);
    2637             : 
    2638       72556 :     res = make_result_opt_error(&result, have_error);
    2639             : 
    2640       72556 :     free_var(&result);
    2641             : 
    2642       72556 :     return res;
    2643             : }
    2644             : 
    2645             : 
    2646             : /*
    2647             :  * numeric_div_trunc() -
    2648             :  *
    2649             :  *  Divide one numeric into another, truncating the result to an integer
    2650             :  */
    2651             : Datum
    2652         248 : numeric_div_trunc(PG_FUNCTION_ARGS)
    2653             : {
    2654         248 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2655         248 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2656             :     NumericVar  arg1;
    2657             :     NumericVar  arg2;
    2658             :     NumericVar  result;
    2659             :     Numeric     res;
    2660             : 
    2661             :     /*
    2662             :      * Handle NaN
    2663             :      */
    2664         248 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2665           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    2666             : 
    2667             :     /*
    2668             :      * Unpack the arguments
    2669             :      */
    2670         248 :     init_var_from_num(num1, &arg1);
    2671         248 :     init_var_from_num(num2, &arg2);
    2672             : 
    2673        1240 :     init_var(&result);
    2674             : 
    2675             :     /*
    2676             :      * Do the divide and return the result
    2677             :      */
    2678         248 :     div_var(&arg1, &arg2, &result, 0, false);
    2679             : 
    2680         248 :     res = make_result(&result);
    2681             : 
    2682         248 :     free_var(&result);
    2683             : 
    2684         248 :     PG_RETURN_NUMERIC(res);
    2685             : }
    2686             : 
    2687             : 
    2688             : /*
    2689             :  * numeric_mod() -
    2690             :  *
    2691             :  *  Calculate the modulo of two numerics
    2692             :  */
    2693             : Datum
    2694          52 : numeric_mod(PG_FUNCTION_ARGS)
    2695             : {
    2696          52 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2697          52 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2698             :     Numeric     res;
    2699             : 
    2700          52 :     res = numeric_mod_opt_error(num1, num2, NULL);
    2701             : 
    2702          52 :     PG_RETURN_NUMERIC(res);
    2703             : }
    2704             : 
    2705             : 
    2706             : /*
    2707             :  * numeric_mod_opt_error() -
    2708             :  *
    2709             :  *  Internal version of numeric_mod().  If "*have_error" flag is provided,
    2710             :  *  on error it's set to true, NULL returned.  This is helpful when caller
    2711             :  *  need to handle errors by itself.
    2712             :  */
    2713             : Numeric
    2714          60 : numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
    2715             : {
    2716             :     Numeric     res;
    2717             :     NumericVar  arg1;
    2718             :     NumericVar  arg2;
    2719             :     NumericVar  result;
    2720             : 
    2721          60 :     if (have_error)
    2722           0 :         *have_error = false;
    2723             : 
    2724          60 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2725           0 :         return make_result(&const_nan);
    2726             : 
    2727          60 :     init_var_from_num(num1, &arg1);
    2728          60 :     init_var_from_num(num2, &arg2);
    2729             : 
    2730         300 :     init_var(&result);
    2731             : 
    2732             :     /*
    2733             :      * If "have_error" is provided, check for division by zero here
    2734             :      */
    2735          60 :     if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
    2736             :     {
    2737           0 :         *have_error = true;
    2738           0 :         return NULL;
    2739             :     }
    2740             : 
    2741          60 :     mod_var(&arg1, &arg2, &result);
    2742             : 
    2743          56 :     res = make_result_opt_error(&result, NULL);
    2744             : 
    2745          56 :     free_var(&result);
    2746             : 
    2747          56 :     return res;
    2748             : }
    2749             : 
    2750             : 
    2751             : /*
    2752             :  * numeric_inc() -
    2753             :  *
    2754             :  *  Increment a number by one
    2755             :  */
    2756             : Datum
    2757           0 : numeric_inc(PG_FUNCTION_ARGS)
    2758             : {
    2759           0 :     Numeric     num = PG_GETARG_NUMERIC(0);
    2760             :     NumericVar  arg;
    2761             :     Numeric     res;
    2762             : 
    2763             :     /*
    2764             :      * Handle NaN
    2765             :      */
    2766           0 :     if (NUMERIC_IS_NAN(num))
    2767           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    2768             : 
    2769             :     /*
    2770             :      * Compute the result and return it
    2771             :      */
    2772           0 :     init_var_from_num(num, &arg);
    2773             : 
    2774           0 :     add_var(&arg, &const_one, &arg);
    2775             : 
    2776           0 :     res = make_result(&arg);
    2777             : 
    2778           0 :     free_var(&arg);
    2779             : 
    2780           0 :     PG_RETURN_NUMERIC(res);
    2781             : }
    2782             : 
    2783             : 
    2784             : /*
    2785             :  * numeric_smaller() -
    2786             :  *
    2787             :  *  Return the smaller of two numbers
    2788             :  */
    2789             : Datum
    2790          72 : numeric_smaller(PG_FUNCTION_ARGS)
    2791             : {
    2792          72 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2793          72 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2794             : 
    2795             :     /*
    2796             :      * Use cmp_numerics so that this will agree with the comparison operators,
    2797             :      * particularly as regards comparisons involving NaN.
    2798             :      */
    2799          72 :     if (cmp_numerics(num1, num2) < 0)
    2800          28 :         PG_RETURN_NUMERIC(num1);
    2801             :     else
    2802          44 :         PG_RETURN_NUMERIC(num2);
    2803             : }
    2804             : 
    2805             : 
    2806             : /*
    2807             :  * numeric_larger() -
    2808             :  *
    2809             :  *  Return the larger of two numbers
    2810             :  */
    2811             : Datum
    2812           0 : numeric_larger(PG_FUNCTION_ARGS)
    2813             : {
    2814           0 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2815           0 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2816             : 
    2817             :     /*
    2818             :      * Use cmp_numerics so that this will agree with the comparison operators,
    2819             :      * particularly as regards comparisons involving NaN.
    2820             :      */
    2821           0 :     if (cmp_numerics(num1, num2) > 0)
    2822           0 :         PG_RETURN_NUMERIC(num1);
    2823             :     else
    2824           0 :         PG_RETURN_NUMERIC(num2);
    2825             : }
    2826             : 
    2827             : 
    2828             : /* ----------------------------------------------------------------------
    2829             :  *
    2830             :  * Advanced math functions
    2831             :  *
    2832             :  * ----------------------------------------------------------------------
    2833             :  */
    2834             : 
    2835             : /*
    2836             :  * numeric_gcd() -
    2837             :  *
    2838             :  *  Calculate the greatest common divisor of two numerics
    2839             :  */
    2840             : Datum
    2841          96 : numeric_gcd(PG_FUNCTION_ARGS)
    2842             : {
    2843          96 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2844          96 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2845             :     NumericVar  arg1;
    2846             :     NumericVar  arg2;
    2847             :     NumericVar  result;
    2848             :     Numeric     res;
    2849             : 
    2850             :     /*
    2851             :      * Handle NaN
    2852             :      */
    2853          96 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2854          16 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    2855             : 
    2856             :     /*
    2857             :      * Unpack the arguments
    2858             :      */
    2859          80 :     init_var_from_num(num1, &arg1);
    2860          80 :     init_var_from_num(num2, &arg2);
    2861             : 
    2862         400 :     init_var(&result);
    2863             : 
    2864             :     /*
    2865             :      * Find the GCD and return the result
    2866             :      */
    2867          80 :     gcd_var(&arg1, &arg2, &result);
    2868             : 
    2869          80 :     res = make_result(&result);
    2870             : 
    2871          80 :     free_var(&result);
    2872             : 
    2873          80 :     PG_RETURN_NUMERIC(res);
    2874             : }
    2875             : 
    2876             : 
    2877             : /*
    2878             :  * numeric_lcm() -
    2879             :  *
    2880             :  *  Calculate the least common multiple of two numerics
    2881             :  */
    2882             : Datum
    2883         116 : numeric_lcm(PG_FUNCTION_ARGS)
    2884             : {
    2885         116 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2886         116 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2887             :     NumericVar  arg1;
    2888             :     NumericVar  arg2;
    2889             :     NumericVar  result;
    2890             :     Numeric     res;
    2891             : 
    2892             :     /*
    2893             :      * Handle NaN
    2894             :      */
    2895         116 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2896          16 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    2897             : 
    2898             :     /*
    2899             :      * Unpack the arguments
    2900             :      */
    2901         100 :     init_var_from_num(num1, &arg1);
    2902         100 :     init_var_from_num(num2, &arg2);
    2903             : 
    2904         500 :     init_var(&result);
    2905             : 
    2906             :     /*
    2907             :      * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
    2908             :      * zero if either input is zero.
    2909             :      *
    2910             :      * Note that the division is guaranteed to be exact, returning an integer
    2911             :      * result, so the LCM is an integral multiple of both x and y.  A display
    2912             :      * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
    2913             :      * but as with other numeric functions, we choose to return a result whose
    2914             :      * display scale is no smaller than either input.
    2915             :      */
    2916         100 :     if (arg1.ndigits == 0 || arg2.ndigits == 0)
    2917          32 :         set_var_from_var(&const_zero, &result);
    2918             :     else
    2919             :     {
    2920          68 :         gcd_var(&arg1, &arg2, &result);
    2921          68 :         div_var(&arg1, &result, &result, 0, false);
    2922          68 :         mul_var(&arg2, &result, &result, arg2.dscale);
    2923          68 :         result.sign = NUMERIC_POS;
    2924             :     }
    2925             : 
    2926         100 :     result.dscale = Max(arg1.dscale, arg2.dscale);
    2927             : 
    2928         100 :     res = make_result(&result);
    2929             : 
    2930          96 :     free_var(&result);
    2931             : 
    2932          96 :     PG_RETURN_NUMERIC(res);
    2933             : }
    2934             : 
    2935             : 
    2936             : /*
    2937             :  * numeric_fac()
    2938             :  *
    2939             :  * Compute factorial
    2940             :  */
    2941             : Datum
    2942          12 : numeric_fac(PG_FUNCTION_ARGS)
    2943             : {
    2944          12 :     int64       num = PG_GETARG_INT64(0);
    2945             :     Numeric     res;
    2946             :     NumericVar  fact;
    2947             :     NumericVar  result;
    2948             : 
    2949          12 :     if (num <= 1)
    2950             :     {
    2951           0 :         res = make_result(&const_one);
    2952           0 :         PG_RETURN_NUMERIC(res);
    2953             :     }
    2954             :     /* Fail immediately if the result would overflow */
    2955          12 :     if (num > 32177)
    2956           0 :         ereport(ERROR,
    2957             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2958             :                  errmsg("value overflows numeric format")));
    2959             : 
    2960          60 :     init_var(&fact);
    2961          60 :     init_var(&result);
    2962             : 
    2963          12 :     int64_to_numericvar(num, &result);
    2964             : 
    2965          24 :     for (num = num - 1; num > 1; num--)
    2966             :     {
    2967             :         /* this loop can take awhile, so allow it to be interrupted */
    2968          12 :         CHECK_FOR_INTERRUPTS();
    2969             : 
    2970          12 :         int64_to_numericvar(num, &fact);
    2971             : 
    2972          12 :         mul_var(&result, &fact, &result, 0);
    2973             :     }
    2974             : 
    2975          12 :     res = make_result(&result);
    2976             : 
    2977          12 :     free_var(&fact);
    2978          12 :     free_var(&result);
    2979             : 
    2980          12 :     PG_RETURN_NUMERIC(res);
    2981             : }
    2982             : 
    2983             : 
    2984             : /*
    2985             :  * numeric_sqrt() -
    2986             :  *
    2987             :  *  Compute the square root of a numeric.
    2988             :  */
    2989             : Datum
    2990          72 : numeric_sqrt(PG_FUNCTION_ARGS)
    2991             : {
    2992          72 :     Numeric     num = PG_GETARG_NUMERIC(0);
    2993             :     Numeric     res;
    2994             :     NumericVar  arg;
    2995             :     NumericVar  result;
    2996             :     int         sweight;
    2997             :     int         rscale;
    2998             : 
    2999             :     /*
    3000             :      * Handle NaN
    3001             :      */
    3002          72 :     if (NUMERIC_IS_NAN(num))
    3003           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3004             : 
    3005             :     /*
    3006             :      * Unpack the argument and determine the result scale.  We choose a scale
    3007             :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
    3008             :      * case not less than the input's dscale.
    3009             :      */
    3010          72 :     init_var_from_num(num, &arg);
    3011             : 
    3012         360 :     init_var(&result);
    3013             : 
    3014             :     /* Assume the input was normalized, so arg.weight is accurate */
    3015          72 :     sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
    3016             : 
    3017          72 :     rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
    3018          72 :     rscale = Max(rscale, arg.dscale);
    3019          72 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    3020          72 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    3021             : 
    3022             :     /*
    3023             :      * Let sqrt_var() do the calculation and return the result.
    3024             :      */
    3025          72 :     sqrt_var(&arg, &result, rscale);
    3026             : 
    3027          72 :     res = make_result(&result);
    3028             : 
    3029          72 :     free_var(&result);
    3030             : 
    3031          72 :     PG_RETURN_NUMERIC(res);
    3032             : }
    3033             : 
    3034             : 
    3035             : /*
    3036             :  * numeric_exp() -
    3037             :  *
    3038             :  *  Raise e to the power of x
    3039             :  */
    3040             : Datum
    3041          32 : numeric_exp(PG_FUNCTION_ARGS)
    3042             : {
    3043          32 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3044             :     Numeric     res;
    3045             :     NumericVar  arg;
    3046             :     NumericVar  result;
    3047             :     int         rscale;
    3048             :     double      val;
    3049             : 
    3050             :     /*
    3051             :      * Handle NaN
    3052             :      */
    3053          32 :     if (NUMERIC_IS_NAN(num))
    3054           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3055             : 
    3056             :     /*
    3057             :      * Unpack the argument and determine the result scale.  We choose a scale
    3058             :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
    3059             :      * case not less than the input's dscale.
    3060             :      */
    3061          32 :     init_var_from_num(num, &arg);
    3062             : 
    3063         160 :     init_var(&result);
    3064             : 
    3065             :     /* convert input to float8, ignoring overflow */
    3066          32 :     val = numericvar_to_double_no_overflow(&arg);
    3067             : 
    3068             :     /*
    3069             :      * log10(result) = num * log10(e), so this is approximately the decimal
    3070             :      * weight of the result:
    3071             :      */
    3072          32 :     val *= 0.434294481903252;
    3073             : 
    3074             :     /* limit to something that won't cause integer overflow */
    3075          32 :     val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
    3076          32 :     val = Min(val, NUMERIC_MAX_RESULT_SCALE);
    3077             : 
    3078          32 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
    3079          32 :     rscale = Max(rscale, arg.dscale);
    3080          32 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    3081          32 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    3082             : 
    3083             :     /*
    3084             :      * Let exp_var() do the calculation and return the result.
    3085             :      */
    3086          32 :     exp_var(&arg, &result, rscale);
    3087             : 
    3088          32 :     res = make_result(&result);
    3089             : 
    3090          32 :     free_var(&result);
    3091             : 
    3092          32 :     PG_RETURN_NUMERIC(res);
    3093             : }
    3094             : 
    3095             : 
    3096             : /*
    3097             :  * numeric_ln() -
    3098             :  *
    3099             :  *  Compute the natural logarithm of x
    3100             :  */
    3101             : Datum
    3102         104 : numeric_ln(PG_FUNCTION_ARGS)
    3103             : {
    3104         104 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3105             :     Numeric     res;
    3106             :     NumericVar  arg;
    3107             :     NumericVar  result;
    3108             :     int         ln_dweight;
    3109             :     int         rscale;
    3110             : 
    3111             :     /*
    3112             :      * Handle NaN
    3113             :      */
    3114         104 :     if (NUMERIC_IS_NAN(num))
    3115           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3116             : 
    3117         104 :     init_var_from_num(num, &arg);
    3118         520 :     init_var(&result);
    3119             : 
    3120             :     /* Estimated dweight of logarithm */
    3121         104 :     ln_dweight = estimate_ln_dweight(&arg);
    3122             : 
    3123         104 :     rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
    3124         104 :     rscale = Max(rscale, arg.dscale);
    3125         104 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    3126         104 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    3127             : 
    3128         104 :     ln_var(&arg, &result, rscale);
    3129             : 
    3130          96 :     res = make_result(&result);
    3131             : 
    3132          96 :     free_var(&result);
    3133             : 
    3134          96 :     PG_RETURN_NUMERIC(res);
    3135             : }
    3136             : 
    3137             : 
    3138             : /*
    3139             :  * numeric_log() -
    3140             :  *
    3141             :  *  Compute the logarithm of x in a given base
    3142             :  */
    3143             : Datum
    3144         104 : numeric_log(PG_FUNCTION_ARGS)
    3145             : {
    3146         104 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3147         104 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3148             :     Numeric     res;
    3149             :     NumericVar  arg1;
    3150             :     NumericVar  arg2;
    3151             :     NumericVar  result;
    3152             : 
    3153             :     /*
    3154             :      * Handle NaN
    3155             :      */
    3156         104 :     if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    3157           0 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3158             : 
    3159             :     /*
    3160             :      * Initialize things
    3161             :      */
    3162         104 :     init_var_from_num(num1, &arg1);
    3163         104 :     init_var_from_num(num2, &arg2);
    3164         520 :     init_var(&result);
    3165             : 
    3166             :     /*
    3167             :      * Call log_var() to compute and return the result; note it handles scale
    3168             :      * selection itself.
    3169             :      */
    3170         104 :     log_var(&arg1, &arg2, &result);
    3171             : 
    3172          72 :     res = make_result(&result);
    3173             : 
    3174          72 :     free_var(&result);
    3175             : 
    3176          72 :     PG_RETURN_NUMERIC(res);
    3177             : }
    3178             : 
    3179             : 
    3180             : /*
    3181             :  * numeric_power() -
    3182             :  *
    3183             :  *  Raise b to the power of x
    3184             :  */
    3185             : Datum
    3186         172 : numeric_power(PG_FUNCTION_ARGS)
    3187             : {
    3188         172 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3189         172 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3190             :     Numeric     res;
    3191             :     NumericVar  arg1;
    3192             :     NumericVar  arg2;
    3193             :     NumericVar  arg2_trunc;
    3194             :     NumericVar  result;
    3195             : 
    3196             :     /*
    3197             :      * Handle NaN cases.  We follow the POSIX spec for pow(3), which says that
    3198             :      * NaN ^ 0 = 1, and 1 ^ NaN = 1, while all other cases with NaN inputs
    3199             :      * yield NaN (with no error).
    3200             :      */
    3201         172 :     if (NUMERIC_IS_NAN(num1))
    3202             :     {
    3203          12 :         if (!NUMERIC_IS_NAN(num2))
    3204             :         {
    3205           8 :             init_var_from_num(num2, &arg2);
    3206           8 :             if (cmp_var(&arg2, &const_zero) == 0)
    3207           4 :                 PG_RETURN_NUMERIC(make_result(&const_one));
    3208             :         }
    3209           8 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3210             :     }
    3211         160 :     if (NUMERIC_IS_NAN(num2))
    3212             :     {
    3213           8 :         init_var_from_num(num1, &arg1);
    3214           8 :         if (cmp_var(&arg1, &const_one) == 0)
    3215           4 :             PG_RETURN_NUMERIC(make_result(&const_one));
    3216           4 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3217             :     }
    3218             : 
    3219             :     /*
    3220             :      * Initialize things
    3221             :      */
    3222         760 :     init_var(&arg2_trunc);
    3223         760 :     init_var(&result);
    3224         152 :     init_var_from_num(num1, &arg1);
    3225         152 :     init_var_from_num(num2, &arg2);
    3226             : 
    3227         152 :     set_var_from_var(&arg2, &arg2_trunc);
    3228         152 :     trunc_var(&arg2_trunc, 0);
    3229             : 
    3230             :     /*
    3231             :      * The SQL spec requires that we emit a particular SQLSTATE error code for
    3232             :      * certain error conditions.  Specifically, we don't return a
    3233             :      * divide-by-zero error code for 0 ^ -1.
    3234             :      */
    3235         172 :     if (cmp_var(&arg1, &const_zero) == 0 &&
    3236          20 :         cmp_var(&arg2, &const_zero) < 0)
    3237           4 :         ereport(ERROR,
    3238             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    3239             :                  errmsg("zero raised to a negative power is undefined")));
    3240             : 
    3241         156 :     if (cmp_var(&arg1, &const_zero) < 0 &&
    3242           8 :         cmp_var(&arg2, &arg2_trunc) != 0)
    3243           4 :         ereport(ERROR,
    3244             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    3245             :                  errmsg("a negative number raised to a non-integer power yields a complex result")));
    3246             : 
    3247             :     /*
    3248             :      * Call power_var() to compute and return the result; note it handles
    3249             :      * scale selection itself.
    3250             :      */
    3251         144 :     power_var(&arg1, &arg2, &result);
    3252             : 
    3253         136 :     res = make_result(&result);
    3254             : 
    3255         136 :     free_var(&result);
    3256         136 :     free_var(&arg2_trunc);
    3257             : 
    3258         136 :     PG_RETURN_NUMERIC(res);
    3259             : }
    3260             : 
    3261             : /*
    3262             :  * numeric_scale() -
    3263             :  *
    3264             :  *  Returns the scale, i.e. the count of decimal digits in the fractional part
    3265             :  */
    3266             : Datum
    3267          32 : numeric_scale(PG_FUNCTION_ARGS)
    3268             : {
    3269          32 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3270             : 
    3271          32 :     if (NUMERIC_IS_NAN(num))
    3272           4 :         PG_RETURN_NULL();
    3273             : 
    3274          28 :     PG_RETURN_INT32(NUMERIC_DSCALE(num));
    3275             : }
    3276             : 
    3277             : /*
    3278             :  * Calculate minimum scale for value.
    3279             :  */
    3280             : static int
    3281          72 : get_min_scale(NumericVar *var)
    3282             : {
    3283             :     int         min_scale;
    3284             :     int         last_digit_pos;
    3285             : 
    3286             :     /*
    3287             :      * Ordinarily, the input value will be "stripped" so that the last
    3288             :      * NumericDigit is nonzero.  But we don't want to get into an infinite
    3289             :      * loop if it isn't, so explicitly find the last nonzero digit.
    3290             :      */
    3291          72 :     last_digit_pos = var->ndigits - 1;
    3292          72 :     while (last_digit_pos >= 0 &&
    3293          56 :            var->digits[last_digit_pos] == 0)
    3294           0 :         last_digit_pos--;
    3295             : 
    3296          72 :     if (last_digit_pos >= 0)
    3297             :     {
    3298             :         /* compute min_scale assuming that last ndigit has no zeroes */
    3299          56 :         min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
    3300             : 
    3301             :         /*
    3302             :          * We could get a negative result if there are no digits after the
    3303             :          * decimal point.  In this case the min_scale must be zero.
    3304             :          */
    3305          56 :         if (min_scale > 0)
    3306             :         {
    3307             :             /*
    3308             :              * Reduce min_scale if trailing digit(s) in last NumericDigit are
    3309             :              * zero.
    3310             :              */
    3311          40 :             NumericDigit last_digit = var->digits[last_digit_pos];
    3312             : 
    3313         120 :             while (last_digit % 10 == 0)
    3314             :             {
    3315          80 :                 min_scale--;
    3316          80 :                 last_digit /= 10;
    3317             :             }
    3318             :         }
    3319             :         else
    3320          16 :             min_scale = 0;
    3321             :     }
    3322             :     else
    3323          16 :         min_scale = 0;          /* result if input is zero */
    3324             : 
    3325          72 :     return min_scale;
    3326             : }
    3327             : 
    3328             : /*
    3329             :  * Returns minimum scale required to represent supplied value without loss.
    3330             :  */
    3331             : Datum
    3332          44 : numeric_min_scale(PG_FUNCTION_ARGS)
    3333             : {
    3334          44 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3335             :     NumericVar  arg;
    3336             :     int         min_scale;
    3337             : 
    3338          44 :     if (NUMERIC_IS_NAN(num))
    3339           4 :         PG_RETURN_NULL();
    3340             : 
    3341          40 :     init_var_from_num(num, &arg);
    3342          40 :     min_scale = get_min_scale(&arg);
    3343          40 :     free_var(&arg);
    3344             : 
    3345          40 :     PG_RETURN_INT32(min_scale);
    3346             : }
    3347             : 
    3348             : /*
    3349             :  * Reduce scale of numeric value to represent supplied value without loss.
    3350             :  */
    3351             : Datum
    3352          36 : numeric_trim_scale(PG_FUNCTION_ARGS)
    3353             : {
    3354          36 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3355             :     Numeric     res;
    3356             :     NumericVar  result;
    3357             : 
    3358          36 :     if (NUMERIC_IS_NAN(num))
    3359           4 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3360             : 
    3361          32 :     init_var_from_num(num, &result);
    3362          32 :     result.dscale = get_min_scale(&result);
    3363          32 :     res = make_result(&result);
    3364          32 :     free_var(&result);
    3365             : 
    3366          32 :     PG_RETURN_NUMERIC(res);
    3367             : }
    3368             : 
    3369             : 
    3370             : /* ----------------------------------------------------------------------
    3371             :  *
    3372             :  * Type conversion functions
    3373             :  *
    3374             :  * ----------------------------------------------------------------------
    3375             :  */
    3376             : 
    3377             : 
    3378             : Datum
    3379      849380 : int4_numeric(PG_FUNCTION_ARGS)
    3380             : {
    3381      849380 :     int32       val = PG_GETARG_INT32(0);
    3382             :     Numeric     res;
    3383             :     NumericVar  result;
    3384             : 
    3385     4246900 :     init_var(&result);
    3386             : 
    3387      849380 :     int64_to_numericvar((int64) val, &result);
    3388             : 
    3389      849380 :     res = make_result(&result);
    3390             : 
    3391      849380 :     free_var(&result);
    3392             : 
    3393      849380 :     PG_RETURN_NUMERIC(res);
    3394             : }
    3395             : 
    3396             : int32
    3397        2276 : numeric_int4_opt_error(Numeric num, bool *have_error)
    3398             : {
    3399             :     NumericVar  x;
    3400             :     int32       result;
    3401             : 
    3402        2276 :     if (have_error)
    3403         192 :         *have_error = false;
    3404             : 
    3405             :     /* XXX would it be better to return NULL? */
    3406        2276 :     if (NUMERIC_IS_NAN(num))
    3407             :     {
    3408           0 :         if (have_error)
    3409             :         {
    3410           0 :             *have_error = true;
    3411           0 :             return 0;
    3412             :         }
    3413             :         else
    3414             :         {
    3415           0 :             ereport(ERROR,
    3416             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3417             :                      errmsg("cannot convert NaN to integer")));
    3418             :         }
    3419             :     }
    3420             : 
    3421             :     /* Convert to variable format, then convert to int4 */
    3422        2276 :     init_var_from_num(num, &x);
    3423             : 
    3424        2276 :     if (!numericvar_to_int32(&x, &result))
    3425             :     {
    3426          16 :         if (have_error)
    3427             :         {
    3428          16 :             *have_error = true;
    3429          16 :             return 0;
    3430             :         }
    3431             :         else
    3432             :         {
    3433           0 :             ereport(ERROR,
    3434             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    3435             :                      errmsg("integer out of range")));
    3436             :         }
    3437             :     }
    3438             : 
    3439        2260 :     return result;
    3440             : }
    3441             : 
    3442             : Datum
    3443        2084 : numeric_int4(PG_FUNCTION_ARGS)
    3444             : {
    3445        2084 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3446             : 
    3447        2084 :     PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
    3448             : }
    3449             : 
    3450             : /*
    3451             :  * Given a NumericVar, convert it to an int32. If the NumericVar
    3452             :  * exceeds the range of an int32, false is returned, otherwise true is returned.
    3453             :  * The input NumericVar is *not* free'd.
    3454             :  */
    3455             : static bool
    3456        2656 : numericvar_to_int32(const NumericVar *var, int32 *result)
    3457             : {
    3458             :     int64       val;
    3459             : 
    3460        2656 :     if (!numericvar_to_int64(var, &val))
    3461           0 :         return false;
    3462             : 
    3463             :     /* Down-convert to int4 */
    3464        2656 :     *result = (int32) val;
    3465             : 
    3466             :     /* Test for overflow by reverse-conversion. */
    3467        2656 :     return ((int64) *result == val);
    3468             : }
    3469             : 
    3470             : Datum
    3471       17140 : int8_numeric(PG_FUNCTION_ARGS)
    3472             : {
    3473       17140 :     int64       val = PG_GETARG_INT64(0);
    3474             :     Numeric     res;
    3475             :     NumericVar  result;
    3476             : 
    3477       85700 :     init_var(&result);
    3478             : 
    3479       17140 :     int64_to_numericvar(val, &result);
    3480             : 
    3481       17140 :     res = make_result(&result);
    3482             : 
    3483       17140 :     free_var(&result);
    3484             : 
    3485       17140 :     PG_RETURN_NUMERIC(res);
    3486             : }
    3487             : 
    3488             : 
    3489             : Datum
    3490         286 : numeric_int8(PG_FUNCTION_ARGS)
    3491             : {
    3492         286 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3493             :     NumericVar  x;
    3494             :     int64       result;
    3495             : 
    3496             :     /* XXX would it be better to return NULL? */
    3497         286 :     if (NUMERIC_IS_NAN(num))
    3498           0 :         ereport(ERROR,
    3499             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3500             :                  errmsg("cannot convert NaN to bigint")));
    3501             : 
    3502             :     /* Convert to variable format and thence to int8 */
    3503         286 :     init_var_from_num(num, &x);
    3504             : 
    3505         286 :     if (!numericvar_to_int64(&x, &result))
    3506          24 :         ereport(ERROR,
    3507             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    3508             :                  errmsg("bigint out of range")));
    3509             : 
    3510         262 :     PG_RETURN_INT64(result);
    3511             : }
    3512             : 
    3513             : 
    3514             : Datum
    3515           0 : int2_numeric(PG_FUNCTION_ARGS)
    3516             : {
    3517           0 :     int16       val = PG_GETARG_INT16(0);
    3518             :     Numeric     res;
    3519             :     NumericVar  result;
    3520             : 
    3521           0 :     init_var(&result);
    3522             : 
    3523           0 :     int64_to_numericvar((int64) val, &result);
    3524             : 
    3525           0 :     res = make_result(&result);
    3526             : 
    3527           0 :     free_var(&result);
    3528             : 
    3529           0 :     PG_RETURN_NUMERIC(res);
    3530             : }
    3531             : 
    3532             : 
    3533             : Datum
    3534          36 : numeric_int2(PG_FUNCTION_ARGS)
    3535             : {
    3536          36 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3537             :     NumericVar  x;
    3538             :     int64       val;
    3539             :     int16       result;
    3540             : 
    3541             :     /* XXX would it be better to return NULL? */
    3542          36 :     if (NUMERIC_IS_NAN(num))
    3543           0 :         ereport(ERROR,
    3544             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3545             :                  errmsg("cannot convert NaN to smallint")));
    3546             : 
    3547             :     /* Convert to variable format and thence to int8 */
    3548          36 :     init_var_from_num(num, &x);
    3549             : 
    3550          36 :     if (!numericvar_to_int64(&x, &val))
    3551           0 :         ereport(ERROR,
    3552             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    3553             :                  errmsg("smallint out of range")));
    3554             : 
    3555             :     /* Down-convert to int2 */
    3556          36 :     result = (int16) val;
    3557             : 
    3558             :     /* Test for overflow by reverse-conversion. */
    3559          36 :     if ((int64) result != val)
    3560           0 :         ereport(ERROR,
    3561             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    3562             :                  errmsg("smallint out of range")));
    3563             : 
    3564          36 :     PG_RETURN_INT16(result);
    3565             : }
    3566             : 
    3567             : 
    3568             : Datum
    3569         692 : float8_numeric(PG_FUNCTION_ARGS)
    3570             : {
    3571         692 :     float8      val = PG_GETARG_FLOAT8(0);
    3572             :     Numeric     res;
    3573             :     NumericVar  result;
    3574             :     char        buf[DBL_DIG + 100];
    3575             : 
    3576         692 :     if (isnan(val))
    3577          12 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3578             : 
    3579         680 :     if (isinf(val))
    3580           8 :         ereport(ERROR,
    3581             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3582             :                  errmsg("cannot convert infinity to numeric")));
    3583             : 
    3584         672 :     snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
    3585             : 
    3586        3360 :     init_var(&result);
    3587             : 
    3588             :     /* Assume we need not worry about leading/trailing spaces */
    3589         672 :     (void) set_var_from_str(buf, buf, &result);
    3590             : 
    3591         672 :     res = make_result(&result);
    3592             : 
    3593         672 :     free_var(&result);
    3594             : 
    3595         672 :     PG_RETURN_NUMERIC(res);
    3596             : }
    3597             : 
    3598             : 
    3599             : Datum
    3600      335508 : numeric_float8(PG_FUNCTION_ARGS)
    3601             : {
    3602      335508 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3603             :     char       *tmp;
    3604             :     Datum       result;
    3605             : 
    3606      335508 :     if (NUMERIC_IS_NAN(num))
    3607           4 :         PG_RETURN_FLOAT8(get_float8_nan());
    3608             : 
    3609      335504 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
    3610             :                                               NumericGetDatum(num)));
    3611             : 
    3612      335504 :     result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
    3613             : 
    3614      335504 :     pfree(tmp);
    3615             : 
    3616      335504 :     PG_RETURN_DATUM(result);
    3617             : }
    3618             : 
    3619             : 
    3620             : /*
    3621             :  * Convert numeric to float8; if out of range, return +/- HUGE_VAL
    3622             :  *
    3623             :  * (internal helper function, not directly callable from SQL)
    3624             :  */
    3625             : Datum
    3626        2910 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
    3627             : {
    3628        2910 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3629             :     double      val;
    3630             : 
    3631        2910 :     if (NUMERIC_IS_NAN(num))
    3632           0 :         PG_RETURN_FLOAT8(get_float8_nan());
    3633             : 
    3634        2910 :     val = numeric_to_double_no_overflow(num);
    3635             : 
    3636        2910 :     PG_RETURN_FLOAT8(val);
    3637             : }
    3638             : 
    3639             : Datum
    3640       13168 : float4_numeric(PG_FUNCTION_ARGS)
    3641             : {
    3642       13168 :     float4      val = PG_GETARG_FLOAT4(0);
    3643             :     Numeric     res;
    3644             :     NumericVar  result;
    3645             :     char        buf[FLT_DIG + 100];
    3646             : 
    3647       13168 :     if (isnan(val))
    3648           4 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3649             : 
    3650       13164 :     if (isinf(val))
    3651           8 :         ereport(ERROR,
    3652             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3653             :                  errmsg("cannot convert infinity to numeric")));
    3654             : 
    3655       13156 :     snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
    3656             : 
    3657       65780 :     init_var(&result);
    3658             : 
    3659             :     /* Assume we need not worry about leading/trailing spaces */
    3660       13156 :     (void) set_var_from_str(buf, buf, &result);
    3661             : 
    3662       13156 :     res = make_result(&result);
    3663             : 
    3664       13156 :     free_var(&result);
    3665             : 
    3666       13156 :     PG_RETURN_NUMERIC(res);
    3667             : }
    3668             : 
    3669             : 
    3670             : Datum
    3671         502 : numeric_float4(PG_FUNCTION_ARGS)
    3672             : {
    3673         502 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3674             :     char       *tmp;
    3675             :     Datum       result;
    3676             : 
    3677         502 :     if (NUMERIC_IS_NAN(num))
    3678           4 :         PG_RETURN_FLOAT4(get_float4_nan());
    3679             : 
    3680         498 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
    3681             :                                               NumericGetDatum(num)));
    3682             : 
    3683         498 :     result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
    3684             : 
    3685         498 :     pfree(tmp);
    3686             : 
    3687         498 :     PG_RETURN_DATUM(result);
    3688             : }
    3689             : 
    3690             : 
    3691             : /* ----------------------------------------------------------------------
    3692             :  *
    3693             :  * Aggregate functions
    3694             :  *
    3695             :  * The transition datatype for all these aggregates is declared as INTERNAL.
    3696             :  * Actually, it's a pointer to a NumericAggState allocated in the aggregate
    3697             :  * context.  The digit buffers for the NumericVars will be there too.
    3698             :  *
    3699             :  * On platforms which support 128-bit integers some aggregates instead use a
    3700             :  * 128-bit integer based transition datatype to speed up calculations.
    3701             :  *
    3702             :  * ----------------------------------------------------------------------
    3703             :  */
    3704             : 
    3705             : typedef struct NumericAggState
    3706             : {
    3707             :     bool        calcSumX2;      /* if true, calculate sumX2 */
    3708             :     MemoryContext agg_context;  /* context we're calculating in */
    3709             :     int64       N;              /* count of processed numbers */
    3710             :     NumericSumAccum sumX;       /* sum of processed numbers */
    3711             :     NumericSumAccum sumX2;      /* sum of squares of processed numbers */
    3712             :     int         maxScale;       /* maximum scale seen so far */
    3713             :     int64       maxScaleCount;  /* number of values seen with maximum scale */
    3714             :     int64       NaNcount;       /* count of NaN values (not included in N!) */
    3715             : } NumericAggState;
    3716             : 
    3717             : /*
    3718             :  * Prepare state data for a numeric aggregate function that needs to compute
    3719             :  * sum, count and optionally sum of squares of the input.
    3720             :  */
    3721             : static NumericAggState *
    3722      114012 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
    3723             : {
    3724             :     NumericAggState *state;
    3725             :     MemoryContext agg_context;
    3726             :     MemoryContext old_context;
    3727             : 
    3728      114012 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    3729           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    3730             : 
    3731      114012 :     old_context = MemoryContextSwitchTo(agg_context);
    3732             : 
    3733      114012 :     state = (NumericAggState *) palloc0(sizeof(NumericAggState));
    3734      114012 :     state->calcSumX2 = calcSumX2;
    3735      114012 :     state->agg_context = agg_context;
    3736             : 
    3737      114012 :     MemoryContextSwitchTo(old_context);
    3738             : 
    3739      114012 :     return state;
    3740             : }
    3741             : 
    3742             : /*
    3743             :  * Like makeNumericAggState(), but allocate the state in the current memory
    3744             :  * context.
    3745             :  */
    3746             : static NumericAggState *
    3747           0 : makeNumericAggStateCurrentContext(bool calcSumX2)
    3748             : {
    3749             :     NumericAggState *state;
    3750             : 
    3751           0 :     state = (NumericAggState *) palloc0(sizeof(NumericAggState));
    3752           0 :     state->calcSumX2 = calcSumX2;
    3753           0 :     state->agg_context = CurrentMemoryContext;
    3754             : 
    3755           0 :     return state;
    3756             : }
    3757             : 
    3758             : /*
    3759             :  * Accumulate a new input value for numeric aggregate functions.
    3760             :  */
    3761             : static void
    3762     1088904 : do_numeric_accum(NumericAggState *state, Numeric newval)
    3763             : {
    3764             :     NumericVar  X;
    3765             :     NumericVar  X2;
    3766             :     MemoryContext old_context;
    3767             : 
    3768             :     /* Count NaN inputs separately from all else */
    3769     1088904 :     if (NUMERIC_IS_NAN(newval))
    3770             :     {
    3771          28 :         state->NaNcount++;
    3772          28 :         return;
    3773             :     }
    3774             : 
    3775             :     /* load processed number in short-lived context */
    3776     1088876 :     init_var_from_num(newval, &X);
    3777             : 
    3778             :     /*
    3779             :      * Track the highest input dscale that we've seen, to support inverse
    3780             :      * transitions (see do_numeric_discard).
    3781             :      */
    3782     1088876 :     if (X.dscale > state->maxScale)
    3783             :     {
    3784          88 :         state->maxScale = X.dscale;
    3785          88 :         state->maxScaleCount = 1;
    3786             :     }
    3787     1088788 :     else if (X.dscale == state->maxScale)
    3788     1088764 :         state->maxScaleCount++;
    3789             : 
    3790             :     /* if we need X^2, calculate that in short-lived context */
    3791     1088876 :     if (state->calcSumX2)
    3792             :     {
    3793        2000 :         init_var(&X2);
    3794         400 :         mul_var(&X, &X, &X2, X.dscale * 2);
    3795             :     }
    3796             : 
    3797             :     /* The rest of this needs to work in the aggregate context */
    3798     1088876 :     old_context = MemoryContextSwitchTo(state->agg_context);
    3799             : 
    3800     1088876 :     state->N++;
    3801             : 
    3802             :     /* Accumulate sums */
    3803     1088876 :     accum_sum_add(&(state->sumX), &X);
    3804             : 
    3805     1088876 :     if (state->calcSumX2)
    3806         400 :         accum_sum_add(&(state->sumX2), &X2);
    3807             : 
    3808     1088876 :     MemoryContextSwitchTo(old_context);
    3809             : }
    3810             : 
    3811             : /*
    3812             :  * Attempt to remove an input value from the aggregated state.
    3813             :  *
    3814             :  * If the value cannot be removed then the function will return false; the
    3815             :  * possible reasons for failing are described below.
    3816             :  *
    3817             :  * If we aggregate the values 1.01 and 2 then the result will be 3.01.
    3818             :  * If we are then asked to un-aggregate the 1.01 then we must fail as we
    3819             :  * won't be able to tell what the new aggregated value's dscale should be.
    3820             :  * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
    3821             :  * have been zero if we'd really aggregated only 2.
    3822             :  *
    3823             :  * Note: alternatively, we could count the number of inputs with each possible
    3824             :  * dscale (up to some sane limit).  Not yet clear if it's worth the trouble.
    3825             :  */
    3826             : static bool
    3827         228 : do_numeric_discard(NumericAggState *state, Numeric newval)
    3828             : {
    3829             :     NumericVar  X;
    3830             :     NumericVar  X2;
    3831             :     MemoryContext old_context;
    3832             : 
    3833             :     /* Count NaN inputs separately from all else */
    3834         228 :     if (NUMERIC_IS_NAN(newval))
    3835             :     {
    3836           4 :         state->NaNcount--;
    3837           4 :         return true;
    3838             :     }
    3839             : 
    3840             :     /* load processed number in short-lived context */
    3841         224 :     init_var_from_num(newval, &X);
    3842             : 
    3843             :     /*
    3844             :      * state->sumX's dscale is the maximum dscale of any of the inputs.
    3845             :      * Removing the last input with that dscale would require us to recompute
    3846             :      * the maximum dscale of the *remaining* inputs, which we cannot do unless
    3847             :      * no more non-NaN inputs remain at all.  So we report a failure instead,
    3848             :      * and force the aggregation to be redone from scratch.
    3849             :      */
    3850         224 :     if (X.dscale == state->maxScale)
    3851             :     {
    3852         224 :         if (state->maxScaleCount > 1 || state->maxScale == 0)
    3853             :         {
    3854             :             /*
    3855             :              * Some remaining inputs have same dscale, or dscale hasn't gotten
    3856             :              * above zero anyway
    3857             :              */
    3858         212 :             state->maxScaleCount--;
    3859             :         }
    3860          12 :         else if (state->N == 1)
    3861             :         {
    3862             :             /* No remaining non-NaN inputs at all, so reset maxScale */
    3863           8 :             state->maxScale = 0;
    3864           8 :             state->maxScaleCount = 0;
    3865             :         }
    3866             :         else
    3867             :         {
    3868             :             /* Correct new maxScale is uncertain, must fail */
    3869           4 :             return false;
    3870             :         }
    3871             :     }
    3872             : 
    3873             :     /* if we need X^2, calculate that in short-lived context */
    3874         220 :     if (state->calcSumX2)
    3875             :     {
    3876         960 :         init_var(&X2);
    3877         192 :         mul_var(&X, &X, &X2, X.dscale * 2);
    3878             :     }
    3879             : 
    3880             :     /* The rest of this needs to work in the aggregate context */
    3881         220 :     old_context = MemoryContextSwitchTo(state->agg_context);
    3882             : 
    3883         220 :     if (state->N-- > 1)
    3884             :     {
    3885             :         /* Negate X, to subtract it from the sum */
    3886         208 :         X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
    3887         208 :         accum_sum_add(&(state->sumX), &X);
    3888             : 
    3889         208 :         if (state->calcSumX2)
    3890             :         {
    3891             :             /* Negate X^2. X^2 is always positive */
    3892         192 :             X2.sign = NUMERIC_NEG;
    3893         192 :             accum_sum_add(&(state->sumX2), &X2);
    3894             :         }
    3895             :     }
    3896             :     else
    3897             :     {
    3898             :         /* Zero the sums */
    3899             :         Assert(state->N == 0);
    3900             : 
    3901          12 :         accum_sum_reset(&state->sumX);
    3902          12 :         if (state->calcSumX2)
    3903           0 :             accum_sum_reset(&state->sumX2);
    3904             :     }
    3905             : 
    3906         220 :     MemoryContextSwitchTo(old_context);
    3907             : 
    3908         220 :     return true;
    3909             : }
    3910             : 
    3911             : /*
    3912             :  * Generic transition function for numeric aggregates that require sumX2.
    3913             :  */
    3914             : Datum
    3915         292 : numeric_accum(PG_FUNCTION_ARGS)
    3916             : {
    3917             :     NumericAggState *state;
    3918             : 
    3919         292 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    3920             : 
    3921             :     /* Create the state data on the first call */
    3922         292 :     if (state == NULL)
    3923          64 :         state = makeNumericAggState(fcinfo, true);
    3924             : 
    3925         292 :     if (!PG_ARGISNULL(1))
    3926         280 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
    3927             : 
    3928         292 :     PG_RETURN_POINTER(state);
    3929             : }
    3930             : 
    3931             : /*
    3932             :  * Generic combine function for numeric aggregates which require sumX2
    3933             :  */
    3934             : Datum
    3935           0 : numeric_combine(PG_FUNCTION_ARGS)
    3936             : {
    3937             :     NumericAggState *state1;
    3938             :     NumericAggState *state2;
    3939             :     MemoryContext agg_context;
    3940             :     MemoryContext old_context;
    3941             : 
    3942           0 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    3943           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    3944             : 
    3945           0 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    3946           0 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
    3947             : 
    3948           0 :     if (state2 == NULL)
    3949           0 :         PG_RETURN_POINTER(state1);
    3950             : 
    3951             :     /* manually copy all fields from state2 to state1 */
    3952           0 :     if (state1 == NULL)
    3953             :     {
    3954           0 :         old_context = MemoryContextSwitchTo(agg_context);
    3955             : 
    3956           0 :         state1 = makeNumericAggStateCurrentContext(true);
    3957           0 :         state1->N = state2->N;
    3958           0 :         state1->NaNcount = state2->NaNcount;
    3959           0 :         state1->maxScale = state2->maxScale;
    3960           0 :         state1->maxScaleCount = state2->maxScaleCount;
    3961             : 
    3962           0 :         accum_sum_copy(&state1->sumX, &state2->sumX);
    3963           0 :         accum_sum_copy(&state1->sumX2, &state2->sumX2);
    3964             : 
    3965           0 :         MemoryContextSwitchTo(old_context);
    3966             : 
    3967           0 :         PG_RETURN_POINTER(state1);
    3968             :     }
    3969             : 
    3970           0 :     if (state2->N > 0)
    3971             :     {
    3972           0 :         state1->N += state2->N;
    3973           0 :         state1->NaNcount += state2->NaNcount;
    3974             : 
    3975             :         /*
    3976             :          * These are currently only needed for moving aggregates, but let's do
    3977             :          * the right thing anyway...
    3978             :          */
    3979           0 :         if (state2->maxScale > state1->maxScale)
    3980             :         {
    3981           0 :             state1->maxScale = state2->maxScale;
    3982           0 :             state1->maxScaleCount = state2->maxScaleCount;
    3983             :         }
    3984           0 :         else if (state2->maxScale == state1->maxScale)
    3985           0 :             state1->maxScaleCount += state2->maxScaleCount;
    3986             : 
    3987             :         /* The rest of this needs to work in the aggregate context */
    3988           0 :         old_context = MemoryContextSwitchTo(agg_context);
    3989             : 
    3990             :         /* Accumulate sums */
    3991           0 :         accum_sum_combine(&state1->sumX, &state2->sumX);
    3992           0 :         accum_sum_combine(&state1->sumX2, &state2->sumX2);
    3993             : 
    3994           0 :         MemoryContextSwitchTo(old_context);
    3995             :     }
    3996           0 :     PG_RETURN_POINTER(state1);
    3997             : }
    3998             : 
    3999             : /*
    4000             :  * Generic transition function for numeric aggregates that don't require sumX2.
    4001             :  */
    4002             : Datum
    4003     1088544 : numeric_avg_accum(PG_FUNCTION_ARGS)
    4004             : {
    4005             :     NumericAggState *state;
    4006             : 
    4007     1088544 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4008             : 
    4009             :     /* Create the state data on the first call */
    4010     1088544 :     if (state == NULL)
    4011      113924 :         state = makeNumericAggState(fcinfo, false);
    4012             : 
    4013     1088544 :     if (!PG_ARGISNULL(1))
    4014     1088504 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
    4015             : 
    4016     1088544 :     PG_RETURN_POINTER(state);
    4017             : }
    4018             : 
    4019             : /*
    4020             :  * Combine function for numeric aggregates which don't require sumX2
    4021             :  */
    4022             : Datum
    4023           0 : numeric_avg_combine(PG_FUNCTION_ARGS)
    4024             : {
    4025             :     NumericAggState *state1;
    4026             :     NumericAggState *state2;
    4027             :     MemoryContext agg_context;
    4028             :     MemoryContext old_context;
    4029             : 
    4030           0 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    4031           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4032             : 
    4033           0 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4034           0 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
    4035             : 
    4036           0 :     if (state2 == NULL)
    4037           0 :         PG_RETURN_POINTER(state1);
    4038             : 
    4039             :     /* manually copy all fields from state2 to state1 */
    4040           0 :     if (state1 == NULL)
    4041             :     {
    4042           0 :         old_context = MemoryContextSwitchTo(agg_context);
    4043             : 
    4044           0 :         state1 = makeNumericAggStateCurrentContext(false);
    4045           0 :         state1->N = state2->N;
    4046           0 :         state1->NaNcount = state2->NaNcount;
    4047           0 :         state1->maxScale = state2->maxScale;
    4048           0 :         state1->maxScaleCount = state2->maxScaleCount;
    4049             : 
    4050           0 :         accum_sum_copy(&state1->sumX, &state2->sumX);
    4051             : 
    4052           0 :         MemoryContextSwitchTo(old_context);
    4053             : 
    4054           0 :         PG_RETURN_POINTER(state1);
    4055             :     }
    4056             : 
    4057           0 :     if (state2->N > 0)
    4058             :     {
    4059           0 :         state1->N += state2->N;
    4060           0 :         state1->NaNcount += state2->NaNcount;
    4061             : 
    4062             :         /*
    4063             :          * These are currently only needed for moving aggregates, but let's do
    4064             :          * the right thing anyway...
    4065             :          */
    4066           0 :         if (state2->maxScale > state1->maxScale)
    4067             :         {
    4068           0 :             state1->maxScale = state2->maxScale;
    4069           0 :             state1->maxScaleCount = state2->maxScaleCount;
    4070             :         }
    4071           0 :         else if (state2->maxScale == state1->maxScale)
    4072           0 :             state1->maxScaleCount += state2->maxScaleCount;
    4073             : 
    4074             :         /* The rest of this needs to work in the aggregate context */
    4075           0 :         old_context = MemoryContextSwitchTo(agg_context);
    4076             : 
    4077             :         /* Accumulate sums */
    4078           0 :         accum_sum_combine(&state1->sumX, &state2->sumX);
    4079             : 
    4080           0 :         MemoryContextSwitchTo(old_context);
    4081             :     }
    4082           0 :     PG_RETURN_POINTER(state1);
    4083             : }
    4084             : 
    4085             : /*
    4086             :  * numeric_avg_serialize
    4087             :  *      Serialize NumericAggState for numeric aggregates that don't require
    4088             :  *      sumX2.
    4089             :  */
    4090             : Datum
    4091           0 : numeric_avg_serialize(PG_FUNCTION_ARGS)
    4092             : {
    4093             :     NumericAggState *state;
    4094             :     StringInfoData buf;
    4095             :     Datum       temp;
    4096             :     bytea      *sumX;
    4097             :     bytea      *result;
    4098             :     NumericVar  tmp_var;
    4099             : 
    4100             :     /* Ensure we disallow calling when not in aggregate context */
    4101           0 :     if (!AggCheckCallContext(fcinfo, NULL))
    4102           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4103             : 
    4104           0 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
    4105             : 
    4106             :     /*
    4107             :      * This is a little wasteful since make_result converts the NumericVar
    4108             :      * into a Numeric and numeric_send converts it back again. Is it worth
    4109             :      * splitting the tasks in numeric_send into separate functions to stop
    4110             :      * this? Doing so would also remove the fmgr call overhead.
    4111             :      */
    4112           0 :     init_var(&tmp_var);
    4113           0 :     accum_sum_final(&state->sumX, &tmp_var);
    4114             : 
    4115           0 :     temp = DirectFunctionCall1(numeric_send,
    4116             :                                NumericGetDatum(make_result(&tmp_var)));
    4117           0 :     sumX = DatumGetByteaPP(temp);
    4118           0 :     free_var(&tmp_var);
    4119             : 
    4120           0 :     pq_begintypsend(&buf);
    4121             : 
    4122             :     /* N */
    4123           0 :     pq_sendint64(&buf, state->N);
    4124             : 
    4125             :     /* sumX */
    4126           0 :     pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
    4127             : 
    4128             :     /* maxScale */
    4129           0 :     pq_sendint32(&buf, state->maxScale);
    4130             : 
    4131             :     /* maxScaleCount */
    4132           0 :     pq_sendint64(&buf, state->maxScaleCount);
    4133             : 
    4134             :     /* NaNcount */
    4135           0 :     pq_sendint64(&buf, state->NaNcount);
    4136             : 
    4137           0 :     result = pq_endtypsend(&buf);
    4138             : 
    4139           0 :     PG_RETURN_BYTEA_P(result);
    4140             : }
    4141             : 
    4142             : /*
    4143             :  * numeric_avg_deserialize
    4144             :  *      Deserialize bytea into NumericAggState for numeric aggregates that
    4145             :  *      don't require sumX2.
    4146             :  */
    4147             : Datum
    4148           0 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
    4149             : {
    4150             :     bytea      *sstate;
    4151             :     NumericAggState *result;
    4152             :     Datum       temp;
    4153             :     NumericVar  tmp_var;
    4154             :     StringInfoData buf;
    4155             : 
    4156           0 :     if (!AggCheckCallContext(fcinfo, NULL))
    4157           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4158             : 
    4159           0 :     sstate = PG_GETARG_BYTEA_PP(0);
    4160             : 
    4161             :     /*
    4162             :      * Copy the bytea into a StringInfo so that we can "receive" it using the
    4163             :      * standard recv-function infrastructure.
    4164             :      */
    4165           0 :     initStringInfo(&buf);
    4166           0 :     appendBinaryStringInfo(&buf,
    4167           0 :                            VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
    4168             : 
    4169           0 :     result = makeNumericAggStateCurrentContext(false);
    4170             : 
    4171             :     /* N */
    4172           0 :     result->N = pq_getmsgint64(&buf);
    4173             : 
    4174             :     /* sumX */
    4175           0 :     temp = DirectFunctionCall3(numeric_recv,
    4176             :                                PointerGetDatum(&buf),
    4177             :                                ObjectIdGetDatum(InvalidOid),
    4178             :                                Int32GetDatum(-1));
    4179           0 :     init_var_from_num(DatumGetNumeric(temp), &tmp_var);
    4180           0 :     accum_sum_add(&(result->sumX), &tmp_var);
    4181             : 
    4182             :     /* maxScale */
    4183           0 :     result->maxScale = pq_getmsgint(&buf, 4);
    4184             : 
    4185             :     /* maxScaleCount */
    4186           0 :     result->maxScaleCount = pq_getmsgint64(&buf);
    4187             : 
    4188             :     /* NaNcount */
    4189           0 :     result->NaNcount = pq_getmsgint64(&buf);
    4190             : 
    4191           0 :     pq_getmsgend(&buf);
    4192           0 :     pfree(buf.data);
    4193             : 
    4194           0 :     PG_RETURN_POINTER(result);
    4195             : }
    4196             : 
    4197             : /*
    4198             :  * numeric_serialize
    4199             :  *      Serialization function for NumericAggState for numeric aggregates that
    4200             :  *      require sumX2.
    4201             :  */
    4202             : Datum
    4203           0 : numeric_serialize(PG_FUNCTION_ARGS)
    4204             : {
    4205             :     NumericAggState *state;
    4206             :     StringInfoData buf;
    4207             :     Datum       temp;
    4208             :     bytea      *sumX;
    4209             :     NumericVar  tmp_var;
    4210             :     bytea      *sumX2;
    4211             :     bytea      *result;
    4212             : 
    4213             :     /* Ensure we disallow calling when not in aggregate context */
    4214           0 :     if (!AggCheckCallContext(fcinfo, NULL))
    4215           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4216             : 
    4217           0 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
    4218             : 
    4219             :     /*
    4220             :      * This is a little wasteful since make_result converts the NumericVar
    4221             :      * into a Numeric and numeric_send converts it back again. Is it worth
    4222             :      * splitting the tasks in numeric_send into separate functions to stop
    4223             :      * this? Doing so would also remove the fmgr call overhead.
    4224             :      */
    4225           0 :     init_var(&tmp_var);
    4226             : 
    4227           0 :     accum_sum_final(&state->sumX, &tmp_var);
    4228           0 :     temp = DirectFunctionCall1(numeric_send,
    4229             :                                NumericGetDatum(make_result(&tmp_var)));
    4230           0 :     sumX = DatumGetByteaPP(temp);
    4231             : 
    4232           0 :     accum_sum_final(&state->sumX2, &tmp_var);
    4233           0 :     temp = DirectFunctionCall1(numeric_send,
    4234             :                                NumericGetDatum(make_result(&tmp_var)));
    4235           0 :     sumX2 = DatumGetByteaPP(temp);
    4236             : 
    4237           0 :     free_var(&tmp_var);
    4238             : 
    4239           0 :     pq_begintypsend(&buf);
    4240             : 
    4241             :     /* N */
    4242           0 :     pq_sendint64(&buf, state->N);
    4243             : 
    4244             :     /* sumX */
    4245           0 :     pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
    4246             : 
    4247             :     /* sumX2 */
    4248           0 :     pq_sendbytes(&buf, VARDATA_ANY(sumX2), VARSIZE_ANY_EXHDR(sumX2));
    4249             : 
    4250             :     /* maxScale */
    4251           0 :     pq_sendint32(&buf, state->maxScale);
    4252             : 
    4253             :     /* maxScaleCount */
    4254           0 :     pq_sendint64(&buf, state->maxScaleCount);
    4255             : 
    4256             :     /* NaNcount */
    4257           0 :     pq_sendint64(&buf, state->NaNcount);
    4258             : 
    4259           0 :     result = pq_endtypsend(&buf);
    4260             : 
    4261           0 :     PG_RETURN_BYTEA_P(result);
    4262             : }
    4263             : 
    4264             : /*
    4265             :  * numeric_deserialize
    4266             :  *      Deserialization function for NumericAggState for numeric aggregates that
    4267             :  *      require sumX2.
    4268             :  */
    4269             : Datum
    4270           0 : numeric_deserialize(PG_FUNCTION_ARGS)
    4271             : {
    4272             :     bytea      *sstate;
    4273             :     NumericAggState *result;
    4274             :     Datum       temp;
    4275             :     NumericVar  sumX_var;
    4276             :     NumericVar  sumX2_var;
    4277             :     StringInfoData buf;
    4278             : 
    4279           0 :     if (!AggCheckCallContext(fcinfo, NULL))
    4280           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4281             : 
    4282           0 :     sstate = PG_GETARG_BYTEA_PP(0);
    4283             : 
    4284             :     /*
    4285             :      * Copy the bytea into a StringInfo so that we can "receive" it using the
    4286             :      * standard recv-function infrastructure.
    4287             :      */
    4288           0 :     initStringInfo(&buf);
    4289           0 :     appendBinaryStringInfo(&buf,
    4290           0 :                            VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
    4291             : 
    4292           0 :     result = makeNumericAggStateCurrentContext(false);
    4293             : 
    4294             :     /* N */
    4295           0 :     result->N = pq_getmsgint64(&buf);
    4296             : 
    4297             :     /* sumX */
    4298           0 :     temp = DirectFunctionCall3(numeric_recv,
    4299             :                                PointerGetDatum(&buf),
    4300             :                                ObjectIdGetDatum(InvalidOid),
    4301             :                                Int32GetDatum(-1));
    4302           0 :     init_var_from_num(DatumGetNumeric(temp), &sumX_var);
    4303           0 :     accum_sum_add(&(result->sumX), &sumX_var);
    4304             : 
    4305             :     /* sumX2 */
    4306           0 :     temp = DirectFunctionCall3(numeric_recv,
    4307             :                                PointerGetDatum(&buf),
    4308             :                                ObjectIdGetDatum(InvalidOid),
    4309             :                                Int32GetDatum(-1));
    4310           0 :     init_var_from_num(DatumGetNumeric(temp), &sumX2_var);
    4311           0 :     accum_sum_add(&(result->sumX2), &sumX2_var);
    4312             : 
    4313             :     /* maxScale */
    4314           0 :     result->maxScale = pq_getmsgint(&buf, 4);
    4315             : 
    4316             :     /* maxScaleCount */
    4317           0 :     result->maxScaleCount = pq_getmsgint64(&buf);
    4318             : 
    4319             :     /* NaNcount */
    4320           0 :     result->NaNcount = pq_getmsgint64(&buf);
    4321             : 
    4322           0 :     pq_getmsgend(&buf);
    4323           0 :     pfree(buf.data);
    4324             : 
    4325           0 :     PG_RETURN_POINTER(result);
    4326             : }
    4327             : 
    4328             : /*
    4329             :  * Generic inverse transition function for numeric aggregates
    4330             :  * (with or without requirement for X^2).
    4331             :  */
    4332             : Datum
    4333         152 : numeric_accum_inv(PG_FUNCTION_ARGS)
    4334             : {
    4335             :     NumericAggState *state;
    4336             : 
    4337         152 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4338             : 
    4339             :     /* Should not get here with no state */
    4340         152 :     if (state == NULL)
    4341           0 :         elog(ERROR, "numeric_accum_inv called with NULL state");
    4342             : 
    4343         152 :     if (!PG_ARGISNULL(1))
    4344             :     {
    4345             :         /* If we fail to perform the inverse transition, return NULL */
    4346         132 :         if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
    4347           4 :             PG_RETURN_NULL();
    4348             :     }
    4349             : 
    4350         148 :     PG_RETURN_POINTER(state);
    4351             : }
    4352             : 
    4353             : 
    4354             : /*
    4355             :  * Integer data types in general use Numeric accumulators to share code
    4356             :  * and avoid risk of overflow.
    4357             :  *
    4358             :  * However for performance reasons optimized special-purpose accumulator
    4359             :  * routines are used when possible.
    4360             :  *
    4361             :  * On platforms with 128-bit integer support, the 128-bit routines will be
    4362             :  * used when sum(X) or sum(X*X) fit into 128-bit.
    4363             :  *
    4364             :  * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
    4365             :  * accumulators will be used for SUM and AVG of these data types.
    4366             :  */
    4367             : 
    4368             : #ifdef HAVE_INT128
    4369             : typedef struct Int128AggState
    4370             : {
    4371             :     bool        calcSumX2;      /* if true, calculate sumX2 */
    4372             :     int64       N;              /* count of processed numbers */
    4373             :     int128      sumX;           /* sum of processed numbers */
    4374             :     int128      sumX2;          /* sum of squares of processed numbers */
    4375             : } Int128AggState;
    4376             : 
    4377             : /*
    4378             :  * Prepare state data for a 128-bit aggregate function that needs to compute
    4379             :  * sum, count and optionally sum of squares of the input.
    4380             :  */
    4381             : static Int128AggState *
    4382         242 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
    4383             : {
    4384             :     Int128AggState *state;
    4385             :     MemoryContext agg_context;
    4386             :     MemoryContext old_context;
    4387             : 
    4388         242 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    4389           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4390             : 
    4391         242 :     old_context = MemoryContextSwitchTo(agg_context);
    4392             : 
    4393         242 :     state = (Int128AggState *) palloc0(sizeof(Int128AggState));
    4394         242 :     state->calcSumX2 = calcSumX2;
    4395             : 
    4396         242 :     MemoryContextSwitchTo(old_context);
    4397             : 
    4398         242 :     return state;
    4399             : }
    4400             : 
    4401             : /*
    4402             :  * Like makeInt128AggState(), but allocate the state in the current memory
    4403             :  * context.
    4404             :  */
    4405             : static Int128AggState *
    4406          12 : makeInt128AggStateCurrentContext(bool calcSumX2)
    4407             : {
    4408             :     Int128AggState *state;
    4409             : 
    4410          12 :     state = (Int128AggState *) palloc0(sizeof(Int128AggState));
    4411          12 :     state->calcSumX2 = calcSumX2;
    4412             : 
    4413          12 :     return state;
    4414             : }
    4415             : 
    4416             : /*
    4417             :  * Accumulate a new input value for 128-bit aggregate functions.
    4418             :  */
    4419             : static void
    4420      123238 : do_int128_accum(Int128AggState *state, int128 newval)
    4421             : {
    4422      123238 :     if (state->calcSumX2)
    4423       42240 :         state->sumX2 += newval * newval;
    4424             : 
    4425      123238 :     state->sumX += newval;
    4426      123238 :     state->N++;
    4427      123238 : }
    4428             : 
    4429             : /*
    4430             :  * Remove an input value from the aggregated state.
    4431             :  */
    4432             : static void
    4433         208 : do_int128_discard(Int128AggState *state, int128 newval)
    4434             : {
    4435         208 :     if (state->calcSumX2)
    4436         192 :         state->sumX2 -= newval * newval;
    4437             : 
    4438         208 :     state->sumX -= newval;
    4439         208 :     state->N--;
    4440         208 : }
    4441             : 
    4442             : typedef Int128AggState PolyNumAggState;
    4443             : #define makePolyNumAggState makeInt128AggState
    4444             : #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
    4445             : #else
    4446             : typedef NumericAggState PolyNumAggState;
    4447             : #define makePolyNumAggState makeNumericAggState
    4448             : #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
    4449             : #endif
    4450             : 
    4451             : Datum
    4452         132 : int2_accum(PG_FUNCTION_ARGS)
    4453             : {
    4454             :     PolyNumAggState *state;
    4455             : 
    4456         132 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4457             : 
    4458             :     /* Create the state data on the first call */
    4459         132 :     if (state == NULL)
    4460          24 :         state = makePolyNumAggState(fcinfo, true);
    4461             : 
    4462         132 :     if (!PG_ARGISNULL(1))
    4463             :     {
    4464             : #ifdef HAVE_INT128
    4465         120 :         do_int128_accum(state, (int128) PG_GETARG_INT16(1));
    4466             : #else
    4467             :         Numeric     newval;
    4468             : 
    4469             :         newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric,
    4470             :                                                      PG_GETARG_DATUM(1)));
    4471             :         do_numeric_accum(state, newval);
    4472             : #endif
    4473             :     }
    4474             : 
    4475         132 :     PG_RETURN_POINTER(state);
    4476             : }
    4477             : 
    4478             : Datum
    4479       42132 : int4_accum(PG_FUNCTION_ARGS)
    4480             : {
    4481             :     PolyNumAggState *state;
    4482             : 
    4483       42132 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4484             : 
    4485             :     /* Create the state data on the first call */
    4486       42132 :     if (state == NULL)
    4487          48 :         state = makePolyNumAggState(fcinfo, true);
    4488             : 
    4489       42132 :     if (!PG_ARGISNULL(1))
    4490             :     {
    4491             : #ifdef HAVE_INT128
    4492       42120 :         do_int128_accum(state, (int128) PG_GETARG_INT32(1));
    4493             : #else
    4494             :         Numeric     newval;
    4495             : 
    4496             :         newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
    4497             :                                                      PG_GETARG_DATUM(1)));
    4498             :         do_numeric_accum(state, newval);
    4499             : #endif
    4500             :     }
    4501             : 
    4502       42132 :     PG_RETURN_POINTER(state);
    4503             : }
    4504             : 
    4505             : Datum
    4506         132 : int8_accum(PG_FUNCTION_ARGS)
    4507             : {
    4508             :     NumericAggState *state;
    4509             : 
    4510         132 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4511             : 
    4512             :     /* Create the state data on the first call */
    4513         132 :     if (state == NULL)
    4514          24 :         state = makeNumericAggState(fcinfo, true);
    4515             : 
    4516         132 :     if (!PG_ARGISNULL(1))
    4517             :     {
    4518             :         Numeric     newval;
    4519             : 
    4520         120 :         newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
    4521             :                                                      PG_GETARG_DATUM(1)));
    4522         120 :         do_numeric_accum(state, newval);
    4523             :     }
    4524             : 
    4525         132 :     PG_RETURN_POINTER(state);
    4526             : }
    4527             : 
    4528             : /*
    4529             :  * Combine function for numeric aggregates which require sumX2
    4530             :  */
    4531             : Datum
    4532           4 : numeric_poly_combine(PG_FUNCTION_ARGS)
    4533             : {
    4534             :     PolyNumAggState *state1;
    4535             :     PolyNumAggState *state2;
    4536             :     MemoryContext agg_context;
    4537             :     MemoryContext old_context;
    4538             : 
    4539           4 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    4540           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4541             : 
    4542           4 :     state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4543           4 :     state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
    4544             : 
    4545           4 :     if (state2 == NULL)
    4546           0 :         PG_RETURN_POINTER(state1);
    4547             : 
    4548             :     /* manually copy all fields from state2 to state1 */
    4549           4 :     if (state1 == NULL)
    4550             :     {
    4551           4 :         old_context = MemoryContextSwitchTo(agg_context);
    4552             : 
    4553           4 :         state1 = makePolyNumAggState(fcinfo, true);
    4554           4 :         state1->N = state2->N;
    4555             : 
    4556             : #ifdef HAVE_INT128
    4557           4 :         state1->sumX = state2->sumX;
    4558           4 :         state1->sumX2 = state2->sumX2;
    4559             : #else
    4560             :         accum_sum_copy(&state1->sumX, &state2->sumX);
    4561             :         accum_sum_copy(&state1->sumX2, &state2->sumX2);
    4562             : #endif
    4563             : 
    4564           4 :         MemoryContextSwitchTo(old_context);
    4565             : 
    4566           4 :         PG_RETURN_POINTER(state1);
    4567             :     }
    4568             : 
    4569           0 :     if (state2->N > 0)
    4570             :     {
    4571           0 :         state1->N += state2->N;
    4572             : 
    4573             : #ifdef HAVE_INT128
    4574           0 :         state1->sumX += state2->sumX;
    4575           0 :         state1->sumX2 += state2->sumX2;
    4576             : #else
    4577             :         /* The rest of this needs to work in the aggregate context */
    4578             :         old_context = MemoryContextSwitchTo(agg_context);
    4579             : 
    4580             :         /* Accumulate sums */
    4581             :         accum_sum_combine(&state1->sumX, &state2->sumX);
    4582             :         accum_sum_combine(&state1->sumX2, &state2->sumX2);
    4583             : 
    4584             :         MemoryContextSwitchTo(old_context);
    4585             : #endif
    4586             : 
    4587             :     }
    4588           0 :     PG_RETURN_POINTER(state1);
    4589             : }
    4590             : 
    4591             : /*
    4592             :  * numeric_poly_serialize
    4593             :  *      Serialize PolyNumAggState into bytea for aggregate functions which
    4594             :  *      require sumX2.
    4595             :  */
    4596             : Datum
    4597           4 : numeric_poly_serialize(PG_FUNCTION_ARGS)
    4598             : {
    4599             :     PolyNumAggState *state;
    4600             :     StringInfoData buf;
    4601             :     bytea      *sumX;
    4602             :     bytea      *sumX2;
    4603             :     bytea      *result;
    4604             : 
    4605             :     /* Ensure we disallow calling when not in aggregate context */
    4606           4 :     if (!AggCheckCallContext(fcinfo, NULL))
    4607           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4608             : 
    4609           4 :     state = (PolyNumAggState *) PG_GETARG_POINTER(0);
    4610             : 
    4611             :     /*
    4612             :      * If the platform supports int128 then sumX and sumX2 will be a 128 bit
    4613             :      * integer type. Here we'll convert that into a numeric type so that the
    4614             :      * combine state is in the same format for both int128 enabled machines
    4615             :      * and machines which don't support that type. The logic here is that one
    4616             :      * day we might like to send these over to another server for further
    4617             :      * processing and we want a standard format to work with.
    4618             :      */
    4619             :     {
    4620             :         Datum       temp;
    4621             :         NumericVar  num;
    4622             : 
    4623          20 :         init_var(&num);
    4624             : 
    4625             : #ifdef HAVE_INT128
    4626           4 :         int128_to_numericvar(state->sumX, &num);
    4627             : #else
    4628             :         accum_sum_final(&state->sumX, &num);
    4629             : #endif
    4630           4 :         temp = DirectFunctionCall1(numeric_send,
    4631             :                                    NumericGetDatum(make_result(&num)));
    4632           4 :         sumX = DatumGetByteaPP(temp);
    4633             : 
    4634             : #ifdef HAVE_INT128
    4635           4 :         int128_to_numericvar(state->sumX2, &num);
    4636             : #else
    4637             :         accum_sum_final(&state->sumX2, &num);
    4638             : #endif
    4639           4 :         temp = DirectFunctionCall1(numeric_send,
    4640             :                                    NumericGetDatum(make_result(&num)));
    4641           4 :         sumX2 = DatumGetByteaPP(temp);
    4642             : 
    4643           4 :         free_var(&num);
    4644             :     }
    4645             : 
    4646           4 :     pq_begintypsend(&buf);
    4647             : 
    4648             :     /* N */
    4649           4 :     pq_sendint64(&buf, state->N);
    4650             : 
    4651             :     /* sumX */
    4652           4 :     pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
    4653             : 
    4654             :     /* sumX2 */
    4655           4 :     pq_sendbytes(&buf, VARDATA_ANY(sumX2), VARSIZE_ANY_EXHDR(sumX2));
    4656             : 
    4657           4 :     result = pq_endtypsend(&buf);
    4658             : 
    4659           4 :     PG_RETURN_BYTEA_P(result);
    4660             : }
    4661             : 
    4662             : /*
    4663             :  * numeric_poly_deserialize
    4664             :  *      Deserialize PolyNumAggState from bytea for aggregate functions which
    4665             :  *      require sumX2.
    4666             :  */
    4667             : Datum
    4668           4 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
    4669             : {
    4670             :     bytea      *sstate;
    4671             :     PolyNumAggState *result;
    4672             :     Datum       sumX;
    4673             :     NumericVar  sumX_var;
    4674             :     Datum       sumX2;
    4675             :     NumericVar  sumX2_var;
    4676             :     StringInfoData buf;
    4677             : 
    4678           4 :     if (!AggCheckCallContext(fcinfo, NULL))
    4679           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4680             : 
    4681           4 :     sstate = PG_GETARG_BYTEA_PP(0);
    4682             : 
    4683             :     /*
    4684             :      * Copy the bytea into a StringInfo so that we can "receive" it using the
    4685             :      * standard recv-function infrastructure.
    4686             :      */
    4687           4 :     initStringInfo(&buf);
    4688           8 :     appendBinaryStringInfo(&buf,
    4689           8 :                            VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
    4690             : 
    4691           4 :     result = makePolyNumAggStateCurrentContext(false);
    4692             : 
    4693             :     /* N */
    4694           4 :     result->N = pq_getmsgint64(&buf);
    4695             : 
    4696             :     /* sumX */
    4697           4 :     sumX = DirectFunctionCall3(numeric_recv,
    4698             :                                PointerGetDatum(&buf),
    4699             :                                ObjectIdGetDatum(InvalidOid),
    4700             :                                Int32GetDatum(-1));
    4701             : 
    4702             :     /* sumX2 */
    4703           4 :     sumX2 = DirectFunctionCall3(numeric_recv,
    4704             :                                 PointerGetDatum(&buf),
    4705             :                                 ObjectIdGetDatum(InvalidOid),
    4706             :                                 Int32GetDatum(-1));
    4707             : 
    4708           4 :     init_var_from_num(DatumGetNumeric(sumX), &sumX_var);
    4709             : #ifdef HAVE_INT128
    4710           4 :     numericvar_to_int128(&sumX_var, &result->sumX);
    4711             : #else
    4712             :     accum_sum_add(&result->sumX, &sumX_var);
    4713             : #endif
    4714             : 
    4715           4 :     init_var_from_num(DatumGetNumeric(sumX2), &sumX2_var);
    4716             : #ifdef HAVE_INT128
    4717           4 :     numericvar_to_int128(&sumX2_var, &result->sumX2);
    4718             : #else
    4719             :     accum_sum_add(&result->sumX2, &sumX2_var);
    4720             : #endif
    4721             : 
    4722           4 :     pq_getmsgend(&buf);
    4723           4 :     pfree(buf.data);
    4724             : 
    4725           4 :     PG_RETURN_POINTER(result);
    4726             : }
    4727             : 
    4728             : /*
    4729             :  * Transition function for int8 input when we don't need sumX2.
    4730             :  */
    4731             : Datum
    4732       81038 : int8_avg_accum(PG_FUNCTION_ARGS)
    4733             : {
    4734             :     PolyNumAggState *state;
    4735             : 
    4736       81038 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4737             : 
    4738             :     /* Create the state data on the first call */
    4739       81038 :     if (state == NULL)
    4740         158 :         state = makePolyNumAggState(fcinfo, false);
    4741             : 
    4742       81038 :     if (!PG_ARGISNULL(1))
    4743             :     {
    4744             : #ifdef HAVE_INT128
    4745       80998 :         do_int128_accum(state, (int128) PG_GETARG_INT64(1));
    4746             : #else
    4747             :         Numeric     newval;
    4748             : 
    4749             :         newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
    4750             :                                                      PG_GETARG_DATUM(1)));
    4751             :         do_numeric_accum(state, newval);
    4752             : #endif
    4753             :     }
    4754             : 
    4755       81038 :     PG_RETURN_POINTER(state);
    4756             : }
    4757             : 
    4758             : /*
    4759             :  * Combine function for PolyNumAggState for aggregates which don't require
    4760             :  * sumX2
    4761             :  */
    4762             : Datum
    4763           8 : int8_avg_combine(PG_FUNCTION_ARGS)
    4764             : {
    4765             :     PolyNumAggState *state1;
    4766             :     PolyNumAggState *state2;
    4767             :     MemoryContext agg_context;
    4768             :     MemoryContext old_context;
    4769             : 
    4770           8 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    4771           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4772             : 
    4773           8 :     state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4774           8 :     state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
    4775             : 
    4776           8 :     if (state2 == NULL)
    4777           0 :         PG_RETURN_POINTER(state1);
    4778             : 
    4779             :     /* manually copy all fields from state2 to state1 */
    4780           8 :     if (state1 == NULL)
    4781             :     {
    4782           8 :         old_context = MemoryContextSwitchTo(agg_context);
    4783             : 
    4784           8 :         state1 = makePolyNumAggState(fcinfo, false);
    4785           8 :         state1->N = state2->N;
    4786             : 
    4787             : #ifdef HAVE_INT128
    4788           8 :         state1->sumX = state2->sumX;
    4789             : #else
    4790             :         accum_sum_copy(&state1->sumX, &state2->sumX);
    4791             : #endif
    4792           8 :         MemoryContextSwitchTo(old_context);
    4793             : 
    4794           8 :         PG_RETURN_POINTER(state1);
    4795             :     }
    4796             : 
    4797           0 :     if (state2->N > 0)
    4798             :     {
    4799           0 :         state1->N += state2->N;
    4800             : 
    4801             : #ifdef HAVE_INT128
    4802           0 :         state1->sumX += state2->sumX;
    4803             : #else
    4804             :         /* The rest of this needs to work in the aggregate context */
    4805             :         old_context = MemoryContextSwitchTo(agg_context);
    4806             : 
    4807             :         /* Accumulate sums */
    4808             :         accum_sum_combine(&state1->sumX, &state2->sumX);
    4809             : 
    4810             :         MemoryContextSwitchTo(old_context);
    4811             : #endif
    4812             : 
    4813             :     }
    4814           0 :     PG_RETURN_POINTER(state1);
    4815             : }
    4816             : 
    4817             : /*
    4818             :  * int8_avg_serialize
    4819             :  *      Serialize PolyNumAggState into bytea using the standard
    4820             :  *      recv-function infrastructure.
    4821             :  */
    4822             : Datum
    4823           8 : int8_avg_serialize(PG_FUNCTION_ARGS)
    4824             : {
    4825             :     PolyNumAggState *state;
    4826             :     StringInfoData buf;
    4827             :     bytea      *sumX;
    4828             :     bytea      *result;
    4829             : 
    4830             :     /* Ensure we disallow calling when not in aggregate context */
    4831           8 :     if (!AggCheckCallContext(fcinfo, NULL))
    4832           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4833             : 
    4834           8 :     state = (PolyNumAggState *) PG_GETARG_POINTER(0);
    4835             : 
    4836             :     /*
    4837             :      * If the platform supports int128 then sumX will be a 128 integer type.
    4838             :      * Here we'll convert that into a numeric type so that the combine state
    4839             :      * is in the same format for both int128 enabled machines and machines
    4840             :      * which don't support that type. The logic here is that one day we might
    4841             :      * like to send these over to another server for further processing and we
    4842             :      * want a standard format to work with.
    4843             :      */
    4844             :     {
    4845             :         Datum       temp;
    4846             :         NumericVar  num;
    4847             : 
    4848          40 :         init_var(&num);
    4849             : 
    4850             : #ifdef HAVE_INT128
    4851           8 :         int128_to_numericvar(state->sumX, &num);
    4852             : #else
    4853             :         accum_sum_final(&state->sumX, &num);
    4854             : #endif
    4855           8 :         temp = DirectFunctionCall1(numeric_send,
    4856             :                                    NumericGetDatum(make_result(&num)));
    4857           8 :         sumX = DatumGetByteaPP(temp);
    4858             : 
    4859           8 :         free_var(&num);
    4860             :     }
    4861             : 
    4862           8 :     pq_begintypsend(&buf);
    4863             : 
    4864             :     /* N */
    4865           8 :     pq_sendint64(&buf, state->N);
    4866             : 
    4867             :     /* sumX */
    4868           8 :     pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
    4869             : 
    4870           8 :     result = pq_endtypsend(&buf);
    4871             : 
    4872           8 :     PG_RETURN_BYTEA_P(result);
    4873             : }
    4874             : 
    4875             : /*
    4876             :  * int8_avg_deserialize
    4877             :  *      Deserialize bytea back into PolyNumAggState.
    4878             :  */
    4879             : Datum
    4880           8 : int8_avg_deserialize(PG_FUNCTION_ARGS)
    4881             : {
    4882             :     bytea      *sstate;
    4883             :     PolyNumAggState *result;
    4884             :     StringInfoData buf;
    4885             :     Datum       temp;
    4886             :     NumericVar  num;
    4887             : 
    4888           8 :     if (!AggCheckCallContext(fcinfo, NULL))
    4889           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4890             : 
    4891           8 :     sstate = PG_GETARG_BYTEA_PP(0);
    4892             : 
    4893             :     /*
    4894             :      * Copy the bytea into a StringInfo so that we can "receive" it using the
    4895             :      * standard recv-function infrastructure.
    4896             :      */
    4897           8 :     initStringInfo(&buf);
    4898          16 :     appendBinaryStringInfo(&buf,
    4899          16 :                            VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
    4900             : 
    4901           8 :     result = makePolyNumAggStateCurrentContext(false);
    4902             : 
    4903             :     /* N */
    4904           8 :     result->N = pq_getmsgint64(&buf);
    4905             : 
    4906             :     /* sumX */
    4907           8 :     temp = DirectFunctionCall3(numeric_recv,
    4908             :                                PointerGetDatum(&buf),
    4909             :                                ObjectIdGetDatum(InvalidOid),
    4910             :                                Int32GetDatum(-1));
    4911           8 :     init_var_from_num(DatumGetNumeric(temp), &num);
    4912             : #ifdef HAVE_INT128
    4913           8 :     numericvar_to_int128(&num, &result->sumX);
    4914             : #else
    4915             :     accum_sum_add(&result->sumX, &num);
    4916             : #endif
    4917             : 
    4918           8 :     pq_getmsgend(&buf);
    4919           8 :     pfree(buf.data);
    4920             : 
    4921           8 :     PG_RETURN_POINTER(result);
    4922             : }
    4923             : 
    4924             : /*
    4925             :  * Inverse transition functions to go with the above.
    4926             :  */
    4927             : 
    4928             : Datum
    4929         108 : int2_accum_inv(PG_FUNCTION_ARGS)
    4930             : {
    4931             :     PolyNumAggState *state;
    4932             : 
    4933         108 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4934             : 
    4935             :     /* Should not get here with no state */
    4936         108 :     if (state == NULL)
    4937           0 :         elog(ERROR, "int2_accum_inv called with NULL state");
    4938             : 
    4939         108 :     if (!PG_ARGISNULL(1))
    4940             :     {
    4941             : #ifdef HAVE_INT128
    4942          96 :         do_int128_discard(state, (int128) PG_GETARG_INT16(1));
    4943             : #else
    4944             :         Numeric     newval;
    4945             : 
    4946             :         newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric,
    4947             :                                                      PG_GETARG_DATUM(1)));
    4948             : 
    4949             :         /* Should never fail, all inputs have dscale 0 */
    4950             :         if (!do_numeric_discard(state, newval))
    4951             :             elog(ERROR, "do_numeric_discard failed unexpectedly");
    4952             : #endif
    4953             :     }
    4954             : 
    4955         108 :     PG_RETURN_POINTER(state);
    4956             : }
    4957             : 
    4958             : Datum
    4959         108 : int4_accum_inv(PG_FUNCTION_ARGS)
    4960             : {
    4961             :     PolyNumAggState *state;
    4962             : 
    4963         108 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    4964             : 
    4965             :     /* Should not get here with no state */
    4966         108 :     if (state == NULL)
    4967           0 :         elog(ERROR, "int4_accum_inv called with NULL state");
    4968             : 
    4969         108 :     if (!PG_ARGISNULL(1))
    4970             :     {
    4971             : #ifdef HAVE_INT128
    4972          96 :         do_int128_discard(state, (int128) PG_GETARG_INT32(1));
    4973             : #else
    4974             :         Numeric     newval;
    4975             : 
    4976             :         newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
    4977             :                                                      PG_GETARG_DATUM(1)));
    4978             : 
    4979             :         /* Should never fail, all inputs have dscale 0 */
    4980             :         if (!do_numeric_discard(state, newval))
    4981             :             elog(ERROR, "do_numeric_discard failed unexpectedly");
    4982             : #endif
    4983             :     }
    4984             : 
    4985         108 :     PG_RETURN_POINTER(state);
    4986             : }
    4987             : 
    4988             : Datum
    4989         108 : int8_accum_inv(PG_FUNCTION_ARGS)
    4990             : {
    4991             :     NumericAggState *state;
    4992             : 
    4993         108 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4994             : 
    4995             :     /* Should not get here with no state */
    4996         108 :     if (state == NULL)
    4997           0 :         elog(ERROR, "int8_accum_inv called with NULL state");
    4998             : 
    4999         108 :     if (!PG_ARGISNULL(1))
    5000             :     {
    5001             :         Numeric     newval;
    5002             : 
    5003          96 :         newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
    5004             :                                                      PG_GETARG_DATUM(1)));
    5005             : 
    5006             :         /* Should never fail, all inputs have dscale 0 */
    5007          96 :         if (!do_numeric_discard(state, newval))
    5008           0 :             elog(ERROR, "do_numeric_discard failed unexpectedly");
    5009             :     }
    5010             : 
    5011         108 :     PG_RETURN_POINTER(state);
    5012             : }
    5013             : 
    5014             : Datum
    5015          24 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
    5016             : {
    5017             :     PolyNumAggState *state;
    5018             : 
    5019          24 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5020             : 
    5021             :     /* Should not get here with no state */
    5022          24 :     if (state == NULL)
    5023           0 :         elog(ERROR, "int8_avg_accum_inv called with NULL state");
    5024             : 
    5025          24 :     if (!PG_ARGISNULL(1))
    5026             :     {
    5027             : #ifdef HAVE_INT128
    5028          16 :         do_int128_discard(state, (int128) PG_GETARG_INT64(1));
    5029             : #else
    5030             :         Numeric     newval;
    5031             : 
    5032             :         newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
    5033             :                                                      PG_GETARG_DATUM(1)));
    5034             : 
    5035             :         /* Should never fail, all inputs have dscale 0 */
    5036             :         if (!do_numeric_discard(state, newval))
    5037             :             elog(ERROR, "do_numeric_discard failed unexpectedly");
    5038             : #endif
    5039             :     }
    5040             : 
    5041          24 :     PG_RETURN_POINTER(state);
    5042             : }
    5043             : 
    5044             : Datum
    5045         310 : numeric_poly_sum(PG_FUNCTION_ARGS)
    5046             : {
    5047             : #ifdef HAVE_INT128
    5048             :     PolyNumAggState *state;
    5049             :     Numeric     res;
    5050             :     NumericVar  result;
    5051             : 
    5052         310 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5053             : 
    5054             :     /* If there were no non-null inputs, return NULL */
    5055         310 :     if (state == NULL || state->N == 0)
    5056          16 :         PG_RETURN_NULL();
    5057             : 
    5058        1470 :     init_var(&result);
    5059             : 
    5060         294 :     int128_to_numericvar(state->sumX, &result);
    5061             : 
    5062         294 :     res = make_result(&result);
    5063             : 
    5064         294 :     free_var(&result);
    5065             : 
    5066         294 :     PG_RETURN_NUMERIC(res);
    5067             : #else
    5068             :     return numeric_sum(fcinfo);
    5069             : #endif
    5070             : }
    5071             : 
    5072             : Datum
    5073          28 : numeric_poly_avg(PG_FUNCTION_ARGS)
    5074             : {
    5075             : #ifdef HAVE_INT128
    5076             :     PolyNumAggState *state;
    5077             :     NumericVar  result;
    5078             :     Datum       countd,
    5079             :                 sumd;
    5080             : 
    5081          28 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5082             : 
    5083             :     /* If there were no non-null inputs, return NULL */
    5084          28 :     if (state == NULL || state->N == 0)
    5085          12 :         PG_RETURN_NULL();
    5086             : 
    5087          80 :     init_var(&result);
    5088             : 
    5089          16 :     int128_to_numericvar(state->sumX, &result);
    5090             : 
    5091          16 :     countd = DirectFunctionCall1(int8_numeric,
    5092             :                                  Int64GetDatumFast(state->N));
    5093          16 :     sumd = NumericGetDatum(make_result(&result));
    5094             : 
    5095          16 :     free_var(&result);
    5096             : 
    5097          16 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
    5098             : #else
    5099             :     return numeric_avg(fcinfo);
    5100             : #endif
    5101             : }
    5102             : 
    5103             : Datum
    5104          28 : numeric_avg(PG_FUNCTION_ARGS)
    5105             : {
    5106             :     NumericAggState *state;
    5107             :     Datum       N_datum;
    5108             :     Datum       sumX_datum;
    5109             :     NumericVar  sumX_var;
    5110             : 
    5111          28 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5112             : 
    5113             :     /* If there were no non-null inputs, return NULL */
    5114          28 :     if (state == NULL || (state->N + state->NaNcount) == 0)
    5115          12 :         PG_RETURN_NULL();
    5116             : 
    5117          16 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
    5118           4 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    5119             : 
    5120          12 :     N_datum = DirectFunctionCall1(int8_numeric, Int64GetDatum(state->N));
    5121             : 
    5122          60 :     init_var(&sumX_var);
    5123          12 :     accum_sum_final(&state->sumX, &sumX_var);
    5124          12 :     sumX_datum = NumericGetDatum(make_result(&sumX_var));
    5125          12 :     free_var(&sumX_var);
    5126             : 
    5127          12 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
    5128             : }
    5129             : 
    5130             : Datum
    5131      113940 : numeric_sum(PG_FUNCTION_ARGS)
    5132             : {
    5133             :     NumericAggState *state;
    5134             :     NumericVar  sumX_var;
    5135             :     Numeric     result;
    5136             : 
    5137      113940 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5138             : 
    5139             :     /* If there were no non-null inputs, return NULL */
    5140      113940 :     if (state == NULL || (state->N + state->NaNcount) == 0)
    5141          12 :         PG_RETURN_NULL();
    5142             : 
    5143      113928 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
    5144          12 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    5145             : 
    5146      569580 :     init_var(&sumX_var);
    5147      113916 :     accum_sum_final(&state->sumX, &sumX_var);
    5148      113916 :     result = make_result(&sumX_var);
    5149      113916 :     free_var(&sumX_var);
    5150             : 
    5151      113916 :     PG_RETURN_NUMERIC(result);
    5152             : }
    5153             : 
    5154             : /*
    5155             :  * Workhorse routine for the standard deviance and variance
    5156             :  * aggregates. 'state' is aggregate's transition state.
    5157             :  * 'variance' specifies whether we should calculate the
    5158             :  * variance or the standard deviation. 'sample' indicates whether the
    5159             :  * caller is interested in the sample or the population
    5160             :  * variance/stddev.
    5161             :  *
    5162             :  * If appropriate variance statistic is undefined for the input,
    5163             :  * *is_null is set to true and NULL is returned.
    5164             :  */
    5165             : static Numeric
    5166         592 : numeric_stddev_internal(NumericAggState *state,
    5167             :                         bool variance, bool sample,
    5168             :                         bool *is_null)
    5169             : {
    5170             :     Numeric     res;
    5171             :     NumericVar  vN,
    5172             :                 vsumX,
    5173             :                 vsumX2,
    5174             :                 vNminus1;
    5175             :     const NumericVar *comp;
    5176             :     int         rscale;
    5177             : 
    5178             :     /* Deal with empty input and NaN-input cases */
    5179         592 :     if (state == NULL || (state->N + state->NaNcount) == 0)
    5180             :     {
    5181           0 :         *is_null = true;
    5182           0 :         return NULL;
    5183             :     }
    5184             : 
    5185         592 :     *is_null = false;
    5186             : 
    5187         592 :     if (state->NaNcount > 0)
    5188           0 :         return make_result(&const_nan);
    5189             : 
    5190        2960 :     init_var(&vN);
    5191        2960 :     init_var(&vsumX);
    5192        2960 :     init_var(&vsumX2);
    5193             : 
    5194         592 :     int64_to_numericvar(state->N, &vN);
    5195         592 :     accum_sum_final(&(state->sumX), &vsumX);
    5196         592 :     accum_sum_final(&(state->sumX2), &vsumX2);
    5197             : 
    5198             :     /*
    5199             :      * Sample stddev and variance are undefined when N <= 1; population stddev
    5200             :      * is undefined when N == 0. Return NULL in either case.
    5201             :      */
    5202         592 :     if (sample)
    5203         400 :         comp = &const_one;
    5204             :     else
    5205         192 :         comp = &const_zero;
    5206             : 
    5207         592 :     if (cmp_var(&vN, comp) <= 0)
    5208             :     {
    5209          72 :         *is_null = true;
    5210          72 :         return NULL;
    5211             :     }
    5212             : 
    5213        2600 :     init_var(&vNminus1);
    5214         520 :     sub_var(&vN, &const_one, &vNminus1);
    5215             : 
    5216             :     /* compute rscale for mul_var calls */
    5217         520 :     rscale = vsumX.dscale * 2;
    5218             : 
    5219         520 :     mul_var(&vsumX, &vsumX, &vsumX, rscale);    /* vsumX = sumX * sumX */
    5220         520 :     mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
    5221         520 :     sub_var(&vsumX2, &vsumX, &vsumX2);  /* N * sumX2 - sumX * sumX */
    5222             : 
    5223         520 :     if (cmp_var(&vsumX2, &const_zero) <= 0)
    5224             :     {
    5225             :         /* Watch out for roundoff error producing a negative numerator */
    5226          60 :         res = make_result(&const_zero);
    5227             :     }
    5228             :     else
    5229             :     {
    5230         460 :         if (sample)
    5231         308 :             mul_var(&vN, &vNminus1, &vNminus1, 0);  /* N * (N - 1) */
    5232             :         else
    5233         152 :             mul_var(&vN, &vN, &vNminus1, 0);    /* N * N */
    5234         460 :         rscale = select_div_scale(&vsumX2, &vNminus1);
    5235         460 :         div_var(&vsumX2, &vNminus1, &vsumX, rscale, true);  /* variance */
    5236         460 :         if (!variance)
    5237         252 :             sqrt_var(&vsumX, &vsumX, rscale);   /* stddev */
    5238             : 
    5239         460 :         res = make_result(&vsumX);
    5240             :     }
    5241             : 
    5242         520 :     free_var(&vNminus1);
    5243         520 :     free_var(&vsumX);
    5244         520 :     free_var(&vsumX2);
    5245             : 
    5246         520 :     return res;
    5247             : }
    5248             : 
    5249             : Datum
    5250          92 : numeric_var_samp(PG_FUNCTION_ARGS)
    5251             : {
    5252             :     NumericAggState *state;
    5253             :     Numeric     res;
    5254             :     bool        is_null;
    5255             : 
    5256          92 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5257             : 
    5258          92 :     res = numeric_stddev_internal(state, true, true, &is_null);
    5259             : 
    5260          92 :     if (is_null)
    5261          20 :         PG_RETURN_NULL();
    5262             :     else
    5263          72 :         PG_RETURN_NUMERIC(res);
    5264             : }
    5265             : 
    5266             : Datum
    5267         108 : numeric_stddev_samp(PG_FUNCTION_ARGS)
    5268             : {
    5269             :     NumericAggState *state;
    5270             :     Numeric     res;
    5271             :     bool        is_null;
    5272             : 
    5273         108 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5274             : 
    5275         108 :     res = numeric_stddev_internal(state, false, true, &is_null);
    5276             : 
    5277         108 :     if (is_null)
    5278          20 :         PG_RETURN_NULL();
    5279             :     else
    5280          88 :         PG_RETURN_NUMERIC(res);
    5281             : }
    5282             : 
    5283             : Datum
    5284          48 : numeric_var_pop(PG_FUNCTION_ARGS)
    5285             : {
    5286             :     NumericAggState *state;
    5287             :     Numeric     res;
    5288             :     bool        is_null;
    5289             : 
    5290          48 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5291             : 
    5292          48 :     res = numeric_stddev_internal(state, true, false, &is_null);
    5293             : 
    5294          48 :     if (is_null)
    5295           0 :         PG_RETURN_NULL();
    5296             :     else
    5297          48 :         PG_RETURN_NUMERIC(res);
    5298             : }
    5299             : 
    5300             : Datum
    5301          56 : numeric_stddev_pop(PG_FUNCTION_ARGS)
    5302             : {
    5303             :     NumericAggState *state;
    5304             :     Numeric     res;
    5305             :     bool        is_null;
    5306             : 
    5307          56 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5308             : 
    5309          56 :     res = numeric_stddev_internal(state, false, false, &is_null);
    5310             : 
    5311          56 :     if (is_null)
    5312           0 :         PG_RETURN_NULL();
    5313             :     else
    5314          56 :         PG_RETURN_NUMERIC(res);
    5315             : }
    5316             : 
    5317             : #ifdef HAVE_INT128
    5318             : static Numeric
    5319         288 : numeric_poly_stddev_internal(Int128AggState *state,
    5320             :                              bool variance, bool sample,
    5321             :                              bool *is_null)
    5322             : {
    5323             :     NumericAggState numstate;
    5324             :     Numeric     res;
    5325             : 
    5326             :     /* Initialize an empty agg state */
    5327         288 :     memset(&numstate, 0, sizeof(NumericAggState));
    5328             : 
    5329         288 :     if (state)
    5330             :     {
    5331             :         NumericVar  tmp_var;
    5332             : 
    5333         288 :         numstate.N = state->N;
    5334             : 
    5335        1440 :         init_var(&tmp_var);
    5336             : 
    5337         288 :         int128_to_numericvar(state->sumX, &tmp_var);
    5338         288 :         accum_sum_add(&numstate.sumX, &tmp_var);
    5339             : 
    5340         288 :         int128_to_numericvar(state->sumX2, &tmp_var);
    5341         288 :         accum_sum_add(&numstate.sumX2, &tmp_var);
    5342             : 
    5343         288 :         free_var(&tmp_var);
    5344             :     }
    5345             : 
    5346         288 :     res = numeric_stddev_internal(&numstate, variance, sample, is_null);
    5347             : 
    5348         288 :     if (numstate.sumX.ndigits > 0)
    5349             :     {
    5350         288 :         pfree(numstate.sumX.pos_digits);
    5351         288 :         pfree(numstate.sumX.neg_digits);
    5352             :     }
    5353         288 :     if (numstate.sumX2.ndigits > 0)
    5354             :     {
    5355         288 :         pfree(numstate.sumX2.pos_digits);
    5356         288 :         pfree(numstate.sumX2.neg_digits);
    5357             :     }
    5358             : 
    5359         288 :     return res;
    5360             : }
    5361             : #endif
    5362             : 
    5363             : Datum
    5364          84 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
    5365             : {
    5366             : #ifdef HAVE_INT128
    5367             :     PolyNumAggState *state;
    5368             :     Numeric     res;
    5369             :     bool        is_null;
    5370             : 
    5371          84 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5372             : 
    5373          84 :     res = numeric_poly_stddev_internal(state, true, true, &is_null);
    5374             : 
    5375          84 :     if (is_null)
    5376          16 :         PG_RETURN_NULL();
    5377             :     else
    5378          68 :         PG_RETURN_NUMERIC(res);
    5379             : #else
    5380             :     return numeric_var_samp(fcinfo);
    5381             : #endif
    5382             : }
    5383             : 
    5384             : Datum
    5385         116 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
    5386             : {
    5387             : #ifdef HAVE_INT128
    5388             :     PolyNumAggState *state;
    5389             :     Numeric     res;
    5390             :     bool        is_null;
    5391             : 
    5392         116 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5393             : 
    5394         116 :     res = numeric_poly_stddev_internal(state, false, true, &is_null);
    5395             : 
    5396         116 :     if (is_null)
    5397          16 :         PG_RETURN_NULL();
    5398             :     else
    5399         100 :         PG_RETURN_NUMERIC(res);
    5400             : #else
    5401             :     return numeric_stddev_samp(fcinfo);
    5402             : #endif
    5403             : }
    5404             : 
    5405             : Datum
    5406          40 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
    5407             : {
    5408             : #ifdef HAVE_INT128
    5409             :     PolyNumAggState *state;
    5410             :     Numeric     res;
    5411             :     bool        is_null;
    5412             : 
    5413          40 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5414             : 
    5415          40 :     res = numeric_poly_stddev_internal(state, true, false, &is_null);
    5416             : 
    5417          40 :     if (is_null)
    5418           0 :         PG_RETURN_NULL();
    5419             :     else
    5420          40 :         PG_RETURN_NUMERIC(res);
    5421             : #else
    5422             :     return numeric_var_pop(fcinfo);
    5423             : #endif
    5424             : }
    5425             : 
    5426             : Datum
    5427          48 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
    5428             : {
    5429             : #ifdef HAVE_INT128
    5430             :     PolyNumAggState *state;
    5431             :     Numeric     res;
    5432             :     bool        is_null;
    5433             : 
    5434          48 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
    5435             : 
    5436          48 :     res = numeric_poly_stddev_internal(state, false, false, &is_null);
    5437             : 
    5438          48 :     if (is_null)
    5439           0 :         PG_RETURN_NULL();
    5440             :     else
    5441          48 :         PG_RETURN_NUMERIC(res);
    5442             : #else
    5443             :     return numeric_stddev_pop(fcinfo);
    5444             : #endif
    5445             : }
    5446             : 
    5447             : /*
    5448             :  * SUM transition functions for integer datatypes.
    5449             :  *
    5450             :  * To avoid overflow, we use accumulators wider than the input datatype.
    5451             :  * A Numeric accumulator is needed for int8 input; for int4 and int2
    5452             :  * inputs, we use int8 accumulators which should be sufficient for practical
    5453             :  * purposes.  (The latter two therefore don't really belong in this file,
    5454             :  * but we keep them here anyway.)
    5455             :  *
    5456             :  * Because SQL defines the SUM() of no values to be NULL, not zero,
    5457             :  * the initial condition of the transition data value needs to be NULL. This
    5458             :  * means we can't rely on ExecAgg to automatically insert the first non-null
    5459             :  * data value into the transition data: it doesn't know how to do the type
    5460             :  * conversion.  The upshot is that these routines have to be marked non-strict
    5461             :  * and handle substitution of the first non-null input themselves.
    5462             :  *
    5463             :  * Note: these functions are used only in plain aggregation mode.
    5464             :  * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
    5465             :  */
    5466             : 
    5467             : Datum
    5468          16 : int2_sum(PG_FUNCTION_ARGS)
    5469             : {
    5470             :     int64       newval;
    5471             : 
    5472          16 :     if (PG_ARGISNULL(0))
    5473             :     {
    5474             :         /* No non-null input seen so far... */
    5475           4 :         if (PG_ARGISNULL(1))
    5476           0 :             PG_RETURN_NULL();   /* still no non-null */
    5477             :         /* This is the first non-null input. */
    5478           4 :         newval = (int64) PG_GETARG_INT16(1);
    5479           4 :         PG_RETURN_INT64(newval);
    5480             :     }
    5481             : 
    5482             :     /*
    5483             :      * If we're invoked as an aggregate, we can cheat and modify our first
    5484             :      * parameter in-place to avoid palloc overhead. If not, we need to return
    5485             :      * the new value of the transition variable. (If int8 is pass-by-value,
    5486             :      * then of course this is useless as well as incorrect, so just ifdef it
    5487             :      * out.)
    5488             :      */
    5489             : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
    5490             :     if (AggCheckCallContext(fcinfo, NULL))
    5491             :     {
    5492             :         int64      *oldsum = (int64 *) PG_GETARG_POINTER(0);
    5493             : 
    5494             :         /* Leave the running sum unchanged in the new input is null */
    5495             :         if (!PG_ARGISNULL(1))
    5496             :             *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
    5497             : 
    5498             :         PG_RETURN_POINTER(oldsum);
    5499             :     }
    5500             :     else
    5501             : #endif
    5502             :     {
    5503          12 :         int64       oldsum = PG_GETARG_INT64(0);
    5504             : 
    5505             :         /* Leave sum unchanged if new input is null. */
    5506          12 :         if (PG_ARGISNULL(1))
    5507           0 :             PG_RETURN_INT64(oldsum);
    5508             : 
    5509             :         /* OK to do the addition. */
    5510          12 :         newval = oldsum + (int64) PG_GETARG_INT16(1);
    5511             : 
    5512          12 :         PG_RETURN_INT64(newval);
    5513             :     }
    5514             : }
    5515             : 
    5516             : Datum
    5517     2075144 : int4_sum(PG_FUNCTION_ARGS)
    5518             : {
    5519             :     int64       newval;
    5520             : 
    5521     2075144 :     if (PG_ARGISNULL(0))
    5522             :     {
    5523             :         /* No non-null input seen so far... */
    5524       77212 :         if (PG_ARGISNULL(1))
    5525         680 :             PG_RETURN_NULL();   /* still no non-null */
    5526             :         /* This is the first non-null input. */
    5527       76532 :         newval = (int64) PG_GETARG_INT32(1);
    5528       76532 :         PG_RETURN_INT64(newval);
    5529             :     }
    5530             : 
    5531             :     /*
    5532             :      * If we're invoked as an aggregate, we can cheat and modify our first
    5533             :      * parameter in-place to avoid palloc overhead. If not, we need to return
    5534             :      * the new value of the transition variable. (If int8 is pass-by-value,
    5535             :      * then of course this is useless as well as incorrect, so just ifdef it
    5536             :      * out.)
    5537             :      */
    5538             : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
    5539             :     if (AggCheckCallContext(fcinfo, NULL))
    5540             :     {
    5541             :         int64      *oldsum = (int64 *) PG_GETARG_POINTER(0);
    5542             : 
    5543             :         /* Leave the running sum unchanged in the new input is null */
    5544             :         if (!PG_ARGISNULL(1))
    5545             :             *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
    5546             : 
    5547             :         PG_RETURN_POINTER(oldsum);
    5548             :     }
    5549             :     else
    5550             : #endif
    5551             :     {
    5552     1997932 :         int64       oldsum = PG_GETARG_INT64(0);
    5553             : 
    5554             :         /* Leave sum unchanged if new input is null. */
    5555     1997932 :         if (PG_ARGISNULL(1))
    5556         584 :             PG_RETURN_INT64(oldsum);
    5557             : 
    5558             :         /* OK to do the addition. */
    5559     1997348 :         newval = oldsum + (int64) PG_GETARG_INT32(1);
    5560             : 
    5561     1997348 :         PG_RETURN_INT64(newval);
    5562             :     }
    5563             : }
    5564             : 
    5565             : /*
    5566             :  * Note: this function is obsolete, it's no longer used for SUM(int8).
    5567             :  */
    5568             : Datum
    5569           0 : int8_sum(PG_FUNCTION_ARGS)
    5570             : {
    5571             :     Numeric     oldsum;
    5572             :     Datum       newval;
    5573             : 
    5574           0 :     if (PG_ARGISNULL(0))
    5575             :     {
    5576             :         /* No non-null input seen so far... */
    5577           0 :         if (PG_ARGISNULL(1))
    5578           0 :             PG_RETURN_NULL();   /* still no non-null */
    5579             :         /* This is the first non-null input. */
    5580           0 :         newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
    5581           0 :         PG_RETURN_DATUM(newval);
    5582             :     }
    5583             : 
    5584             :     /*
    5585             :      * Note that we cannot special-case the aggregate case here, as we do for
    5586             :      * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
    5587             :      * our first parameter in-place.
    5588             :      */
    5589             : 
    5590           0 :     oldsum = PG_GETARG_NUMERIC(0);
    5591             : 
    5592             :     /* Leave sum unchanged if new input is null. */
    5593           0 :     if (PG_ARGISNULL(1))
    5594           0 :         PG_RETURN_NUMERIC(oldsum);
    5595             : 
    5596             :     /* OK to do the addition. */
    5597           0 :     newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
    5598             : 
    5599           0 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
    5600             :                                         NumericGetDatum(oldsum), newval));
    5601             : }
    5602             : 
    5603             : 
    5604             : /*
    5605             :  * Routines for avg(int2) and avg(int4).  The transition datatype
    5606             :  * is a two-element int8 array, holding count and sum.
    5607             :  *
    5608             :  * These functions are also used for sum(int2) and sum(int4) when
    5609             :  * operating in moving-aggregate mode, since for correct inverse transitions
    5610             :  * we need to count the inputs.
    5611             :  */
    5612             : 
    5613             : typedef struct Int8TransTypeData
    5614             : {
    5615             :     int64       count;
    5616             :     int64       sum;
    5617             : } Int8TransTypeData;
    5618             : 
    5619             : Datum
    5620          28 : int2_avg_accum(PG_FUNCTION_ARGS)
    5621             : {
    5622             :     ArrayType  *transarray;
    5623          28 :     int16       newval = PG_GETARG_INT16(1);
    5624             :     Int8TransTypeData *transdata;
    5625             : 
    5626             :     /*
    5627             :      * If we're invoked as an aggregate, we can cheat and modify our first
    5628             :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    5629             :      * a copy of it before scribbling on it.
    5630             :      */
    5631          28 :     if (AggCheckCallContext(fcinfo, NULL))
    5632          28 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    5633             :     else
    5634           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    5635             : 
    5636          28 :     if (ARR_HASNULL(transarray) ||
    5637          28 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5638           0 :         elog(ERROR, "expected 2-element int8 array");
    5639             : 
    5640          28 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    5641          28 :     transdata->count++;
    5642          28 :     transdata->sum += newval;
    5643             : 
    5644          28 :     PG_RETURN_ARRAYTYPE_P(transarray);
    5645             : }
    5646             : 
    5647             : Datum
    5648     1757532 : int4_avg_accum(PG_FUNCTION_ARGS)
    5649             : {
    5650             :     ArrayType  *transarray;
    5651     1757532 :     int32       newval = PG_GETARG_INT32(1);
    5652             :     Int8TransTypeData *transdata;
    5653             : 
    5654             :     /*
    5655             :      * If we're invoked as an aggregate, we can cheat and modify our first
    5656             :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    5657             :      * a copy of it before scribbling on it.
    5658             :      */
    5659     1757532 :     if (AggCheckCallContext(fcinfo, NULL))
    5660     1757532 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    5661             :     else
    5662           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    5663             : 
    5664     1757532 :     if (ARR_HASNULL(transarray) ||
    5665     1757532 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5666           0 :         elog(ERROR, "expected 2-element int8 array");
    5667             : 
    5668     1757532 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    5669     1757532 :     transdata->count++;
    5670     1757532 :     transdata->sum += newval;
    5671             : 
    5672     1757532 :     PG_RETURN_ARRAYTYPE_P(transarray);
    5673             : }
    5674             : 
    5675             : Datum
    5676        2296 : int4_avg_combine(PG_FUNCTION_ARGS)
    5677             : {
    5678             :     ArrayType  *transarray1;
    5679             :     ArrayType  *transarray2;
    5680             :     Int8TransTypeData *state1;
    5681             :     Int8TransTypeData *state2;
    5682             : 
    5683        2296 :     if (!AggCheckCallContext(fcinfo, NULL))
    5684           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5685             : 
    5686        2296 :     transarray1 = PG_GETARG_ARRAYTYPE_P(0);
    5687        2296 :     transarray2 = PG_GETARG_ARRAYTYPE_P(1);
    5688             : 
    5689        2296 :     if (ARR_HASNULL(transarray1) ||
    5690        2296 :         ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5691           0 :         elog(ERROR, "expected 2-element int8 array");
    5692             : 
    5693        2296 :     if (ARR_HASNULL(transarray2) ||
    5694        2296 :         ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5695           0 :         elog(ERROR, "expected 2-element int8 array");
    5696             : 
    5697        2296 :     state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
    5698        2296 :     state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
    5699             : 
    5700        2296 :     state1->count += state2->count;
    5701        2296 :     state1->sum += state2->sum;
    5702             : 
    5703        2296 :     PG_RETURN_ARRAYTYPE_P(transarray1);
    5704             : }
    5705             : 
    5706             : Datum
    5707           8 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
    5708             : {
    5709             :     ArrayType  *transarray;
    5710           8 :     int16       newval = PG_GETARG_INT16(1);
    5711             :     Int8TransTypeData *transdata;
    5712             : 
    5713             :     /*
    5714             :      * If we're invoked as an aggregate, we can cheat and modify our first
    5715             :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    5716             :      * a copy of it before scribbling on it.
    5717             :      */
    5718           8 :     if (AggCheckCallContext(fcinfo, NULL))
    5719           8 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    5720             :     else
    5721           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    5722             : 
    5723           8 :     if (ARR_HASNULL(transarray) ||
    5724           8 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5725           0 :         elog(ERROR, "expected 2-element int8 array");
    5726             : 
    5727           8 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    5728           8 :     transdata->count--;
    5729           8 :     transdata->sum -= newval;
    5730             : 
    5731           8 :     PG_RETURN_ARRAYTYPE_P(transarray);
    5732             : }
    5733             : 
    5734             : Datum
    5735         848 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
    5736             : {
    5737             :     ArrayType  *transarray;
    5738         848 :     int32       newval = PG_GETARG_INT32(1);
    5739             :     Int8TransTypeData *transdata;
    5740             : 
    5741             :     /*
    5742             :      * If we're invoked as an aggregate, we can cheat and modify our first
    5743             :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    5744             :      * a copy of it before scribbling on it.
    5745             :      */
    5746         848 :     if (AggCheckCallContext(fcinfo, NULL))
    5747         848 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    5748             :     else
    5749           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    5750             : 
    5751         848 :     if (ARR_HASNULL(transarray) ||
    5752         848 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5753           0 :         elog(ERROR, "expected 2-element int8 array");
    5754             : 
    5755         848 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    5756         848 :     transdata->count--;
    5757         848 :     transdata->sum -= newval;
    5758             : 
    5759         848 :     PG_RETURN_ARRAYTYPE_P(transarray);
    5760             : }
    5761             : 
    5762             : Datum
    5763        7938 : int8_avg(PG_FUNCTION_ARGS)
    5764             : {
    5765        7938 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    5766             :     Int8TransTypeData *transdata;
    5767             :     Datum       countd,
    5768             :                 sumd;
    5769             : 
    5770        7938 :     if (ARR_HASNULL(transarray) ||
    5771        7938 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5772           0 :         elog(ERROR, "expected 2-element int8 array");
    5773        7938 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    5774             : 
    5775             :     /* SQL defines AVG of no values to be NULL */
    5776        7938 :     if (transdata->count == 0)
    5777          90 :         PG_RETURN_NULL();
    5778             : 
    5779        7848 :     countd = DirectFunctionCall1(int8_numeric,
    5780             :                                  Int64GetDatumFast(transdata->count));
    5781        7848 :     sumd = DirectFunctionCall1(int8_numeric,
    5782             :                                Int64GetDatumFast(transdata->sum));
    5783             : 
    5784        7848 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
    5785             : }
    5786             : 
    5787             : /*
    5788             :  * SUM(int2) and SUM(int4) both return int8, so we can use this
    5789             :  * final function for both.
    5790             :  */
    5791             : Datum
    5792        3520 : int2int4_sum(PG_FUNCTION_ARGS)
    5793             : {
    5794        3520 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    5795             :     Int8TransTypeData *transdata;
    5796             : 
    5797        3520 :     if (ARR_HASNULL(transarray) ||
    5798        3520 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    5799           0 :         elog(ERROR, "expected 2-element int8 array");
    5800        3520 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    5801             : 
    5802             :     /* SQL defines SUM of no values to be NULL */
    5803        3520 :     if (transdata->count == 0)
    5804         332 :         PG_RETURN_NULL();
    5805             : 
    5806        3188 :     PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
    5807             : }
    5808             : 
    5809             : 
    5810             : /* ----------------------------------------------------------------------
    5811             :  *
    5812             :  * Debug support
    5813             :  *
    5814             :  * ----------------------------------------------------------------------
    5815             :  */
    5816             : 
    5817             : #ifdef NUMERIC_DEBUG
    5818             : 
    5819             : /*
    5820             :  * dump_numeric() - Dump a value in the db storage format for debugging
    5821             :  */
    5822             : static void
    5823             : dump_numeric(const char *str, Numeric num)
    5824             : {
    5825             :     NumericDigit *digits = NUMERIC_DIGITS(num);
    5826             :     int         ndigits;
    5827             :     int         i;
    5828             : 
    5829             :     ndigits = NUMERIC_NDIGITS(num);
    5830             : 
    5831             :     printf("%s: NUMERIC w=%d d=%d ", str,
    5832             :            NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
    5833             :     switch (NUMERIC_SIGN(num))
    5834             :     {
    5835             :         case NUMERIC_POS:
    5836             :             printf("POS");
    5837             :             break;
    5838             :         case NUMERIC_NEG:
    5839             :             printf("NEG");
    5840             :             break;
    5841             :         case NUMERIC_NAN:
    5842             :             printf("NaN");
    5843             :             break;
    5844             :         default:
    5845             :             printf("SIGN=0x%x", NUMERIC_SIGN(num));
    5846             :             break;
    5847             :     }
    5848             : 
    5849             :     for (i = 0; i < ndigits; i++)
    5850             :         printf(" %0*d", DEC_DIGITS, digits[i]);
    5851             :     printf("\n");
    5852             : }
    5853             : 
    5854             : 
    5855             : /*
    5856             :  * dump_var() - Dump a value in the variable format for debugging
    5857             :  */
    5858             : static void
    5859             : dump_var(const char *str, NumericVar *var)
    5860             : {
    5861             :     int         i;
    5862             : 
    5863             :     printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
    5864             :     switch (var->sign)
    5865             :     {
    5866             :         case NUMERIC_POS:
    5867             :             printf("POS");
    5868             :             break;
    5869             :         case NUMERIC_NEG:
    5870             :             printf("NEG");
    5871             :             break;
    5872             :         case NUMERIC_NAN:
    5873             :             printf("NaN");
    5874             :             break;
    5875             :         default:
    5876             :             printf("SIGN=0x%x", var->sign);
    5877             :             break;
    5878             :     }
    5879             : 
    5880             :     for (i = 0; i < var->ndigits; i++)
    5881             :         printf(" %0*d", DEC_DIGITS, var->digits[i]);
    5882             : 
    5883             :     printf("\n");
    5884             : }
    5885             : #endif                          /* NUMERIC_DEBUG */
    5886             : 
    5887             : 
    5888             : /* ----------------------------------------------------------------------
    5889             :  *
    5890             :  * Local functions follow
    5891             :  *
    5892             :  * In general, these do not support NaNs --- callers must eliminate
    5893             :  * the possibility of NaN first.  (make_result() is an exception.)
    5894             :  *
    5895             :  * ----------------------------------------------------------------------
    5896             :  */
    5897             : 
    5898             : 
    5899             : /*
    5900             :  * alloc_var() -
    5901             :  *
    5902             :  *  Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
    5903             :  */
    5904             : static void
    5905     1358808 : alloc_var(NumericVar *var, int ndigits)
    5906             : {
    5907     1358808 :     digitbuf_free(var->buf);
    5908     1358808 :     var->buf = digitbuf_alloc(ndigits + 1);
    5909     1358808 :     var->buf[0] = 0;         /* spare digit for rounding */
    5910     1358808 :     var->digits = var->buf + 1;
    5911     1358808 :     var->ndigits = ndigits;
    5912     1358808 : }
    5913             : 
    5914             : 
    5915             : /*
    5916             :  * free_var() -
    5917             :  *
    5918             :  *  Return the digit buffer of a variable to the free pool
    5919             :  */
    5920             : static void
    5921     1494974 : free_var(NumericVar *var)
    5922             : {
    5923     1494974 :     digitbuf_free(var->buf);
    5924     1494974 :     var->buf = NULL;
    5925     1494974 :     var->digits = NULL;
    5926     1494974 :     var->sign = NUMERIC_NAN;
    5927     1494974 : }
    5928             : 
    5929             : 
    5930             : /*
    5931             :  * zero_var() -
    5932             :  *
    5933             :  *  Set a variable to ZERO.
    5934             :  *  Note: its dscale is not touched.
    5935             :  */
    5936             : static void
    5937       27712 : zero_var(NumericVar *var)
    5938             : {
    5939       27712 :     digitbuf_free(var->buf);
    5940       27712 :     var->buf = NULL;
    5941       27712 :     var->digits = NULL;
    5942       27712 :     var->ndigits = 0;
    5943       27712 :     var->weight = 0;         /* by convention; doesn't really matter */
    5944       27712 :     var->sign = NUMERIC_POS; /* anything but NAN... */
    5945       27712 : }
    5946             : 
    5947             : 
    5948             : /*
    5949             :  * set_var_from_str()
    5950             :  *
    5951             :  *  Parse a string and put the number into a variable
    5952             :  *
    5953             :  * This function does not handle leading or trailing spaces, and it doesn't
    5954             :  * accept "NaN" either.  It returns the end+1 position so that caller can
    5955             :  * check for trailing spaces/garbage if deemed necessary.
    5956             :  *
    5957             :  * cp is the place to actually start parsing; str is what to use in error
    5958             :  * reports.  (Typically cp would be the same except advanced over spaces.)
    5959             :  */
    5960             : static const char *
    5961       40900 : set_var_from_str(const char *str, const char *cp, NumericVar *dest)
    5962             : {
    5963       40900 :     bool        have_dp = false;
    5964             :     int         i;
    5965             :     unsigned char *decdigits;
    5966       40900 :     int         sign = NUMERIC_POS;
    5967       40900 :     int         dweight = -1;
    5968             :     int         ddigits;
    5969       40900 :     int         dscale = 0;
    5970             :     int         weight;
    5971             :     int         ndigits;
    5972             :     int         offset;
    5973             :     NumericDigit *digits;
    5974             : 
    5975             :     /*
    5976             :      * We first parse the string to extract decimal digits and determine the
    5977             :      * correct decimal weight.  Then convert to NBASE representation.
    5978             :      */
    5979       40900 :     switch (*cp)
    5980             :     {
    5981           4 :         case '+':
    5982           4 :             sign = NUMERIC_POS;
    5983           4 :             cp++;
    5984           4 :             break;
    5985             : 
    5986        2450 :         case '-':
    5987        2450 :             sign = NUMERIC_NEG;
    5988        2450 :             cp++;
    5989        2450 :             break;
    5990             :     }
    5991             : 
    5992       40900 :     if (*cp == '.')
    5993             :     {
    5994         184 :         have_dp = true;
    5995         184 :         cp++;
    5996             :     }
    5997             : 
    5998       40900 :     if (!isdigit((unsigned char) *cp))
    5999          26 :         ereport(ERROR,
    6000             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    6001             :                  errmsg("invalid input syntax for type %s: \"%s\"",
    6002             :                         "numeric", str)));
    6003             : 
    6004       40874 :     decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
    6005             : 
    6006             :     /* leading padding for digit alignment later */
    6007       40874 :     memset(decdigits, 0, DEC_DIGITS);
    6008       40874 :     i = DEC_DIGITS;
    6009             : 
    6010      188846 :     while (*cp)
    6011             :     {
    6012      148340 :         if (isdigit((unsigned char) *cp))
    6013             :         {
    6014      138208 :             decdigits[i++] = *cp++ - '0';
    6015      138208 :             if (!have_dp)
    6016       95724 :                 dweight++;
    6017             :             else
    6018       42484 :                 dscale++;
    6019             :         }
    6020       10132 :         else if (*cp == '.')
    6021             :         {
    6022        9764 :             if (have_dp)
    6023           0 :                 ereport(ERROR,
    6024             :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    6025             :                          errmsg("invalid input syntax for type %s: \"%s\"",
    6026             :                                 "numeric", str)));
    6027        9764 :             have_dp = true;
    6028        9764 :             cp++;
    6029             :         }
    6030             :         else
    6031         368 :             break;
    6032             :     }
    6033             : 
    6034       40874 :     ddigits = i - DEC_DIGITS;
    6035             :     /* trailing padding for digit alignment later */
    6036       40874 :     memset(decdigits + i, 0, DEC_DIGITS - 1);
    6037             : 
    6038             :     /* Handle exponent, if any */
    6039       40874 :     if (*cp == 'e' || *cp == 'E')
    6040             :     {
    6041             :         long        exponent;
    6042             :         char       *endptr;
    6043             : 
    6044         352 :         cp++;
    6045         352 :         exponent = strtol(cp, &endptr, 10);
    6046         352 :         if (endptr == cp)
    6047           0 :             ereport(ERROR,
    6048             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    6049             :                      errmsg("invalid input syntax for type %s: \"%s\"",
    6050             :                             "numeric", str)));
    6051         352 :         cp = endptr;
    6052             : 
    6053             :         /*
    6054             :          * At this point, dweight and dscale can't be more than about
    6055             :          * INT_MAX/2 due to the MaxAllocSize limit on string length, so
    6056             :          * constraining the exponent similarly should be enough to prevent
    6057             :          * integer overflow in this function.  If the value is too large to
    6058             :          * fit in storage format, make_result() will complain about it later;
    6059             :          * for consistency use the same ereport errcode/text as make_result().
    6060             :          */
    6061         352 :         if (exponent >= INT_MAX / 2 || exponent <= -(INT_MAX / 2))
    6062           4 :             ereport(ERROR,
    6063             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    6064             :                      errmsg("value overflows numeric format")));
    6065         348 :         dweight += (int) exponent;
    6066         348 :         dscale -= (int) exponent;
    6067         348 :         if (dscale < 0)
    6068         144 :             dscale = 0;
    6069             :     }
    6070             : 
    6071             :     /*
    6072             :      * Okay, convert pure-decimal representation to base NBASE.  First we need
    6073             :      * to determine the converted weight and ndigits.  offset is the number of
    6074             :      * decimal zeroes to insert before the first given digit to have a
    6075             :      * correctly aligned first NBASE digit.
    6076             :      */
    6077       40870 :     if (dweight >= 0)
    6078       40570 :         weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
    6079             :     else
    6080         300 :         weight = -((-dweight - 1) / DEC_DIGITS + 1);
    6081       40870 :     offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
    6082       40870 :     ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
    6083             : 
    6084       40870 :     alloc_var(dest, ndigits);
    6085       40870 :     dest->sign = sign;
    6086       40870 :     dest->weight = weight;
    6087       40870 :     dest->dscale = dscale;
    6088             : 
    6089       40870 :     i = DEC_DIGITS - offset;
    6090       40870 :     digits = dest->digits;
    6091             : 
    6092      106316 :     while (ndigits-- > 0)
    6093             :     {
    6094             : #if DEC_DIGITS == 4
    6095      261784 :         *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
    6096      196338 :                      decdigits[i + 2]) * 10 + decdigits[i + 3];
    6097             : #elif DEC_DIGITS == 2
    6098             :         *digits++ = decdigits[i] * 10 + decdigits[i + 1];
    6099             : #elif DEC_DIGITS == 1
    6100             :         *digits++ = decdigits[i];
    6101             : #else
    6102             : #error unsupported NBASE
    6103             : #endif
    6104       65446 :         i += DEC_DIGITS;
    6105             :     }
    6106             : 
    6107       40870 :     pfree(decdigits);
    6108             : 
    6109             :     /* Strip any leading/trailing zeroes, and normalize weight if zero */
    6110       40870 :     strip_var(dest);
    6111             : 
    6112             :     /* Return end+1 position for caller */
    6113       40870 :     return cp;
    6114             : }
    6115             : 
    6116             : 
    6117             : /*
    6118             :  * set_var_from_num() -
    6119             :  *
    6120             :  *  Convert the packed db format into a variable
    6121             :  */
    6122             : static void
    6123        7506 : set_var_from_num(Numeric num, NumericVar *dest)
    6124             : {
    6125             :     int         ndigits;
    6126             : 
    6127        7506 :     ndigits = NUMERIC_NDIGITS(num);
    6128             : 
    6129        7506 :     alloc_var(dest, ndigits);
    6130             : 
    6131        7506 :     dest->weight = NUMERIC_WEIGHT(num);
    6132        7506 :     dest->sign = NUMERIC_SIGN(num);
    6133        7506 :     dest->dscale = NUMERIC_DSCALE(num);
    6134             : 
    6135        7506 :     memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
    6136        7506 : }
    6137             : 
    6138             : 
    6139             : /*
    6140             :  * init_var_from_num() -
    6141             :  *
    6142             :  *  Initialize a variable from packed db format. The digits array is not
    6143             :  *  copied, which saves some cycles when the resulting var is not modified.
    6144             :  *  Also, there's no need to call free_var(), as long as you don't assign any
    6145             :  *  other value to it (with set_var_* functions, or by using the var as the
    6146             :  *  destination of a function like add_var())
    6147             :  *
    6148             :  *  CAUTION: Do not modify the digits buffer of a var initialized with this
    6149             :  *  function, e.g by calling round_var() or trunc_var(), as the changes will
    6150             :  *  propagate to the original Numeric! It's OK to use it as the destination
    6151             :  *  argument of one of the calculational functions, though.
    6152             :  */
    6153             : static void
    6154     2435542 : init_var_from_num(Numeric num, NumericVar *dest)
    6155             : {
    6156     2435542 :     dest->ndigits = NUMERIC_NDIGITS(num);
    6157     2435542 :     dest->weight = NUMERIC_WEIGHT(num);
    6158     2435542 :     dest->sign = NUMERIC_SIGN(num);
    6159     2435542 :     dest->dscale = NUMERIC_DSCALE(num);
    6160     2435542 :     dest->digits = NUMERIC_DIGITS(num);
    6161     2435542 :     dest->buf = NULL;            /* digits array is not palloc'd */
    6162     2435542 : }
    6163             : 
    6164             : 
    6165             : /*
    6166             :  * set_var_from_var() -
    6167             :  *
    6168             :  *  Copy one variable into another
    6169             :  */
    6170             : static void
    6171       17606 : set_var_from_var(const NumericVar *value, NumericVar *dest)
    6172             : {
    6173             :     NumericDigit *newbuf;
    6174             : 
    6175       17606 :     newbuf = digitbuf_alloc(value->ndigits + 1);
    6176       17606 :     newbuf[0] = 0;              /* spare digit for rounding */
    6177       17606 :     if (value->ndigits > 0)       /* else value->digits might be null */
    6178       17202 :         memcpy(newbuf + 1, value->digits,
    6179       17202 :                value->ndigits * sizeof(NumericDigit));
    6180             : 
    6181       17606 :     digitbuf_free(dest->buf);
    6182             : 
    6183       17606 :     memmove(dest, value, sizeof(NumericVar));
    6184       17606 :     dest->buf = newbuf;
    6185       17606 :     dest->digits = newbuf + 1;
    6186       17606 : }
    6187             : 
    6188             : 
    6189             : /*
    6190             :  * get_str_from_var() -
    6191             :  *
    6192             :  *  Convert a var to text representation (guts of numeric_out).
    6193             :  *  The var is displayed to the number of digits indicated by its dscale.
    6194             :  *  Returns a palloc'd string.
    6195             :  */
    6196             : static char *
    6197      471702 : get_str_from_var(const NumericVar *var)
    6198             : {
    6199             :     int         dscale;
    6200             :     char       *str;
    6201             :     char       *cp;
    6202             :     char       *endcp;
    6203             :     int         i;
    6204             :     int         d;
    6205             :     NumericDigit dig;
    6206             : 
    6207             : #if DEC_DIGITS > 1
    6208             :     NumericDigit d1;
    6209             : #endif
    6210             : 
    6211      471702 :     dscale = var->dscale;
    6212             : 
    6213             :     /*
    6214             :      * Allocate space for the result.
    6215             :      *
    6216             :      * i is set to the # of decimal digits before decimal point. dscale is the
    6217             :      * # of decimal digits we will print after decimal point. We may generate
    6218             :      * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
    6219             :      * need room for sign, decimal point, null terminator.
    6220             :      */
    6221      471702 :     i = (var->weight + 1) * DEC_DIGITS;
    6222      471702 :     if (i <= 0)
    6223       64230 :         i = 1;
    6224             : 
    6225      471702 :     str = palloc(i + dscale + DEC_DIGITS + 2);
    6226      471702 :     cp = str;
    6227             : 
    6228             :     /*
    6229             :      * Output a dash for negative values
    6230             :      */
    6231      471702 :     if (var->sign == NUMERIC_NEG)
    6232        2198 :         *cp++ = '-';
    6233             : 
    6234             :     /*
    6235             :      * Output all digits before the decimal point
    6236             :      */
    6237      471702 :     if (var->weight < 0)
    6238             :     {
    6239       64230 :         d = var->weight + 1;
    6240       64230 :         *cp++ = '0';
    6241             :     }
    6242             :     else
    6243             :     {
    6244      886516 :         for (d = 0; d <= var->weight; d++)
    6245             :         {
    6246      479044 :             dig = (d < var->ndigits) ? var->digits[d] : 0;
    6247             :             /* In the first digit, suppress extra leading decimal zeroes */
    6248             : #if DEC_DIGITS == 4
    6249             :             {
    6250      479044 :                 bool        putit = (d > 0);
    6251             : 
    6252      479044 :                 d1 = dig / 1000;
    6253      479044 :                 dig -= d1 * 1000;
    6254      479044 :                 putit |= (d1 > 0);
    6255      479044 :                 if (putit)
    6256       73280 :                     *cp++ = d1 + '0';
    6257      479044 :                 d1 = dig / 100;
    6258      479044 :                 dig -= d1 * 100;
    6259      479044 :                 putit |= (d1 > 0);
    6260      479044 :                 if (putit)
    6261      339892 :                     *cp++ = d1 + '0';
    6262      479044 :                 d1 = dig / 10;
    6263      479044 :                 dig -= d1 * 10;
    6264      479044 :                 putit |= (d1 > 0);
    6265      479044 :                 if (putit)
    6266      418270 :                     *cp++ = d1 + '0';
    6267      479044 :                 *cp++ = dig + '0';
    6268             :             }
    6269             : #elif DEC_DIGITS == 2
    6270             :             d1 = dig / 10;
    6271             :             dig -= d1 * 10;
    6272             :             if (d1 > 0 || d > 0)
    6273             :                 *cp++ = d1 + '0';
    6274             :             *cp++ = dig + '0';
    6275             : #elif DEC_DIGITS == 1
    6276             :             *cp++ = dig + '0';
    6277             : #else
    6278             : #error unsupported NBASE
    6279             : #endif
    6280             :         }
    6281             :     }
    6282             : 
    6283             :     /*
    6284             :      * If requested, output a decimal point and all the digits that follow it.
    6285             :      * We initially put out a multiple of DEC_DIGITS digits, then truncate if
    6286             :      * needed.
    6287             :      */
    6288      471702 :     if (dscale > 0)
    6289             :     {
    6290      393736 :         *cp++ = '.';
    6291      393736 :         endcp = cp + dscale;
    6292     1060056 :         for (i = 0; i < dscale; d++, i += DEC_DIGITS)
    6293             :         {
    6294      666320 :             dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
    6295             : #if DEC_DIGITS == 4
    6296      666320 :             d1 = dig / 1000;
    6297      666320 :             dig -= d1 * 1000;
    6298      666320 :             *cp++ = d1 + '0';
    6299      666320 :             d1 = dig / 100;
    6300      666320 :             dig -= d1 * 100;
    6301      666320 :             *cp++ = d1 + '0';
    6302      666320 :             d1 = dig / 10;
    6303      666320 :             dig -= d1 * 10;
    6304      666320 :             *cp++ = d1 + '0';
    6305      666320 :             *cp++ = dig + '0';
    6306             : #elif DEC_DIGITS == 2
    6307             :             d1 = dig / 10;
    6308             :             dig -= d1 * 10;
    6309             :             *cp++ = d1 + '0';
    6310             :             *cp++ = dig + '0';
    6311             : #elif DEC_DIGITS == 1
    6312             :             *cp++ = dig + '0';
    6313             : #else
    6314             : #error unsupported NBASE
    6315             : #endif
    6316             :         }
    6317      393736 :         cp = endcp;
    6318             :     }
    6319             : 
    6320             :     /*
    6321             :      * terminate the string and return it
    6322             :      */
    6323      471702 :     *cp = '\0';
    6324      471702 :     return str;
    6325             : }
    6326             : 
    6327             : /*
    6328             :  * get_str_from_var_sci() -
    6329             :  *
    6330             :  *  Convert a var to a normalised scientific notation text representation.
    6331             :  *  This function does the heavy lifting for numeric_out_sci().
    6332             :  *
    6333             :  *  This notation has the general form a * 10^b, where a is known as the
    6334             :  *  "significand" and b is known as the "exponent".
    6335             :  *
    6336             :  *  Because we can't do superscript in ASCII (and because we want to copy
    6337             :  *  printf's behaviour) we display the exponent using E notation, with a
    6338             :  *  minimum of two exponent digits.
    6339             :  *
    6340             :  *  For example, the value 1234 could be output as 1.2e+03.
    6341             :  *
    6342             :  *  We assume that the exponent can fit into an int32.
    6343             :  *
    6344             :  *  rscale is the number of decimal digits desired after the decimal point in
    6345             :  *  the output, negative values will be treated as meaning zero.
    6346             :  *
    6347             :  *  Returns a palloc'd string.
    6348             :  */
    6349             : static char *
    6350          40 : get_str_from_var_sci(const NumericVar *var, int rscale)
    6351             : {
    6352             :     int32       exponent;
    6353             :     NumericVar  denominator;
    6354             :     NumericVar  significand;
    6355             :     int         denom_scale;
    6356             :     size_t      len;
    6357             :     char       *str;
    6358             :     char       *sig_out;
    6359             : 
    6360          40 :     if (rscale < 0)
    6361           0 :         rscale = 0;
    6362             : 
    6363             :     /*
    6364             :      * Determine the exponent of this number in normalised form.
    6365             :      *
    6366             :      * This is the exponent required to represent the number with only one
    6367             :      * significant digit before the decimal place.
    6368             :      */
    6369          40 :     if (var->ndigits > 0)
    6370             :     {
    6371          32 :         exponent = (var->weight + 1) * DEC_DIGITS;
    6372             : 
    6373             :         /*
    6374             :          * Compensate for leading decimal zeroes in the first numeric digit by
    6375             :          * decrementing the exponent.
    6376             :          */
    6377          32 :         exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
    6378             :     }
    6379             :     else
    6380             :     {
    6381             :         /*
    6382             :          * If var has no digits, then it must be zero.
    6383             :          *
    6384             :          * Zero doesn't technically have a meaningful exponent in normalised
    6385             :          * notation, but we just display the exponent as zero for consistency
    6386             :          * of output.
    6387             :          */
    6388           8 :         exponent = 0;
    6389             :     }
    6390             : 
    6391             :     /*
    6392             :      * The denominator is set to 10 raised to the power of the exponent.
    6393             :      *
    6394             :      * We then divide var by the denominator to get the significand, rounding
    6395             :      * to rscale decimal digits in the process.
    6396             :      */
    6397          40 :     if (exponent < 0)
    6398           0 :         denom_scale = -exponent;
    6399             :     else
    6400          40 :         denom_scale = 0;
    6401             : 
    6402         200 :     init_var(&denominator);
    6403         200 :     init_var(&significand);
    6404             : 
    6405          40 :     power_var_int(&const_ten, exponent, &denominator, denom_scale);
    6406          40 :     div_var(var, &denominator, &significand, rscale, true);
    6407          40 :     sig_out = get_str_from_var(&significand);
    6408             : 
    6409          40 :     free_var(&denominator);
    6410          40 :     free_var(&significand);
    6411             : 
    6412             :     /*
    6413             :      * Allocate space for the result.
    6414             :      *
    6415             :      * In addition to the significand, we need room for the exponent
    6416             :      * decoration ("e"), the sign of the exponent, up to 10 digits for the
    6417             :      * exponent itself, and of course the null terminator.
    6418             :      */
    6419          40 :     len = strlen(sig_out) + 13;
    6420          40 :     str = palloc(len);
    6421          40 :     snprintf(str, len, "%se%+03d", sig_out, exponent);
    6422             : 
    6423          40 :     pfree(sig_out);
    6424             : 
    6425          40 :     return str;
    6426             : }
    6427             : 
    6428             : 
    6429             : /*
    6430             :  * make_result_opt_error() -
    6431             :  *
    6432             :  *  Create the packed db numeric format in palloc()'d memory from
    6433             :  *  a variable.  If "*have_error" flag is provided, on error it's set to
    6434             :  *  true, NULL returned.  This is helpful when caller need to handle errors
    6435             :  *  by itself.
    6436             :  */
    6437             : static Numeric
    6438     1467816 : make_result_opt_error(const NumericVar *var, bool *have_error)
    6439             : {
    6440             :     Numeric     result;
    6441     1467816 :     NumericDigit *digits = var->digits;
    6442     1467816 :     int         weight = var->weight;
    6443     1467816 :     int         sign = var->sign;
    6444             :     int         n;
    6445             :     Size        len;
    6446             : 
    6447     1467816 :     if (have_error)
    6448          80 :         *have_error = false;
    6449             : 
    6450     1467816 :     if (sign == NUMERIC_NAN)
    6451             :     {
    6452        2804 :         result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
    6453             : 
    6454        2804 :         SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
    6455        2804 :         result->choice.n_header = NUMERIC_NAN;
    6456             :         /* the header word is all we need */
    6457             : 
    6458             :         dump_numeric("make_result()", result);
    6459        2804 :         return result;
    6460             :     }
    6461             : 
    6462     1465012 :     n = var->ndigits;
    6463             : 
    6464             :     /* truncate leading zeroes */
    6465     1465012 :     while (n > 0 && *digits == 0)
    6466             :     {
    6467           0 :         digits++;
    6468           0 :         weight--;
    6469           0 :         n--;
    6470             :     }
    6471             :     /* truncate trailing zeroes */
    6472     1465210 :     while (n > 0 && digits[n - 1] == 0)
    6473         198 :         n--;
    6474             : 
    6475             :     /* If zero result, force to weight=0 and positive sign */
    6476     1465012 :     if (n == 0)
    6477             :     {
    6478       53434 :         weight = 0;
    6479       53434 :         sign = NUMERIC_POS;
    6480             :     }
    6481             : 
    6482             :     /* Build the result */
    6483     1465012 :     if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
    6484             :     {
    6485     1464034 :         len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
    6486     1464034 :         result = (Numeric) palloc(len);
    6487     1464034 :         SET_VARSIZE(result, len);
    6488     1464034 :         result->choice.n_short.n_header =
    6489             :             (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
    6490             :              : NUMERIC_SHORT)
    6491     1464034 :             | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
    6492     1464034 :             | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
    6493     1464034 :             | (weight & NUMERIC_SHORT_WEIGHT_MASK);
    6494             :     }
    6495             :     else
    6496             :     {
    6497         978 :         len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
    6498         978 :         result = (Numeric) palloc(len);
    6499         978 :         SET_VARSIZE(result, len);
    6500         978 :         result->choice.n_long.n_sign_dscale =
    6501         978 :             sign | (var->dscale & NUMERIC_DSCALE_MASK);
    6502         978 :         result->choice.n_long.n_weight = weight;
    6503             :     }
    6504             : 
    6505             :     Assert(NUMERIC_NDIGITS(result) == n);
    6506     1465012 :     if (n > 0)
    6507     1411578 :         memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
    6508             : 
    6509             :     /* Check for overflow of int16 fields */
    6510     1465012 :     if (NUMERIC_WEIGHT(result) != weight ||
    6511     1465008 :         NUMERIC_DSCALE(result) != var->dscale)
    6512             :     {
    6513           4 :         if (have_error)
    6514             :         {
    6515           0 :             *have_error = true;
    6516           0 :             return NULL;
    6517             :         }
    6518             :         else
    6519             :         {
    6520           4 :             ereport(ERROR,
    6521             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    6522             :                      errmsg("value overflows numeric format")));
    6523             :         }
    6524             :     }
    6525             : 
    6526             :     dump_numeric("make_result()", result);
    6527     1465008 :     return result;
    6528             : }
    6529             : 
    6530             : 
    6531             : /*
    6532             :  * make_result() -
    6533             :  *
    6534             :  *  An interface to make_result_opt_error() without "have_error" argument.
    6535             :  */
    6536             : static Numeric
    6537     1033574 : make_result(const NumericVar *var)
    6538             : {
    6539     1033574 :     return make_result_opt_error(var, NULL);
    6540             : }
    6541             : 
    6542             : 
    6543             : /*
    6544             :  * apply_typmod() -
    6545             :  *
    6546             :  *  Do bounds checking and rounding according to the attributes
    6547             :  *  typmod field.
    6548             :  */
    6549             : static void
    6550       29886 : apply_typmod(NumericVar *var, int32 typmod)
    6551             : {
    6552             :     int         precision;
    6553             :     int         scale;
    6554             :     int         maxdigits;
    6555             :     int         ddigits;
    6556             :     int         i;
    6557             : 
    6558             :     /* Do nothing if we have a default typmod (-1) */
    6559       29886 :     if (typmod < (int32) (VARHDRSZ))
    6560       26946 :         return;
    6561             : 
    6562        2940 :     typmod -= VARHDRSZ;
    6563        2940 :     precision = (typmod >> 16) & 0xffff;
    6564        2940 :     scale = typmod & 0xffff;
    6565        2940 :     maxdigits = precision - scale;
    6566             : 
    6567             :     /* Round to target scale (and set var->dscale) */
    6568        2940 :     round_var(var, scale);
    6569             : 
    6570             :     /*
    6571             :      * Check for overflow - note we can't do this before rounding, because
    6572             :      * rounding could raise the weight.  Also note that the var's weight could
    6573             :      * be inflated by leading zeroes, which will be stripped before storage
    6574             :      * but perhaps might not have been yet. In any case, we must recognize a
    6575             :      * true zero, whose weight doesn't mean anything.
    6576             :      */
    6577        2940 :     ddigits = (var->weight + 1) * DEC_DIGITS;
    6578        2940 :     if (ddigits > maxdigits)
    6579             :     {
    6580             :         /* Determine true weight; and check for all-zero result */
    6581         176 :         for (i = 0; i < var->ndigits; i++)
    6582             :         {
    6583         164 :             NumericDigit dig = var->digits[i];
    6584             : 
    6585         164 :             if (dig)
    6586             :             {
    6587             :                 /* Adjust for any high-order decimal zero digits */
    6588             : #if DEC_DIGITS == 4
    6589         164 :                 if (dig < 10)
    6590         132 :                     ddigits -= 3;
    6591          32 :                 else if (dig < 100)
    6592          16 :                     ddigits -= 2;
    6593          16 :                 else if (dig < 1000)
    6594          16 :                     ddigits -= 1;
    6595             : #elif DEC_DIGITS == 2
    6596             :                 if (dig < 10)
    6597             :                     ddigits -= 1;
    6598             : #elif DEC_DIGITS == 1
    6599             :                 /* no adjustment */
    6600             : #else
    6601             : #error unsupported NBASE
    6602             : #endif
    6603         164 :                 if (ddigits > maxdigits)
    6604          20 :                     ereport(ERROR,
    6605             :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    6606             :                              errmsg("numeric field overflow"),
    6607             :                              errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
    6608             :                                        precision, scale,
    6609             :                     /* Display 10^0 as 1 */
    6610             :                                        maxdigits ? "10^" : "",
    6611             :                                        maxdigits ? maxdigits : 1
    6612             :                                        )));
    6613         144 :                 break;
    6614             :             }
    6615           0 :             ddigits -= DEC_DIGITS;
    6616             :         }
    6617             :     }
    6618             : }
    6619             : 
    6620             : /*
    6621             :  * Convert numeric to int8, rounding if needed.
    6622             :  *
    6623             :  * If overflow, return false (no error is raised).  Return true if okay.
    6624             :  */
    6625             : static bool
    6626        3066 : numericvar_to_int64(const NumericVar *var, int64 *result)
    6627             : {
    6628             :     NumericDigit *digits;
    6629             :     int         ndigits;
    6630             :     int         weight;
    6631             :     int         i;
    6632             :     int64       val;
    6633             :     bool        neg;
    6634             :     NumericVar  rounded;
    6635             : 
    6636             :     /* Round to nearest integer */
    6637       15330 :     init_var(&rounded);
    6638        3066 :     set_var_from_var(var, &rounded);
    6639        3066 :     round_var(&rounded, 0);
    6640             : 
    6641             :     /* Check for zero input */
    6642        3066 :     strip_var(&rounded);
    6643        3066 :     ndigits = rounded.ndigits;
    6644        3066 :     if (ndigits == 0)
    6645             :     {
    6646         188 :         *result = 0;
    6647         188 :         free_var(&rounded);
    6648         188 :         return true;
    6649             :     }
    6650             : 
    6651             :     /*
    6652             :      * For input like 10000000000, we must treat stripped digits as real. So
    6653             :      * the loop assumes there are weight+1 digits before the decimal point.
    6654             :      */
    6655        2878 :     weight = rounded.weight;
    6656             :     Assert(weight >= 0 && ndigits <= weight + 1);
    6657             : 
    6658             :     /*
    6659             :      * Construct the result. To avoid issues with converting a value
    6660             :      * corresponding to INT64_MIN (which can't be represented as a positive 64
    6661             :      * bit two's complement integer), accumulate value as a negative number.
    6662             :      */
    6663        2878 :     digits = rounded.digits;
    6664        2878 :     neg = (rounded.sign == NUMERIC_NEG);
    6665        2878 :     val = -digits[0];
    6666        3306 :     for (i = 1; i <= weight; i++)
    6667             :     {
    6668         440 :         if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
    6669             :         {
    6670           4 :             free_var(&rounded);
    6671           4 :             return false;
    6672             :         }
    6673             : 
    6674         436 :         if (i < ndigits)
    6675             :         {
    6676         340 :             if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
    6677             :             {
    6678           8 :                 free_var(&rounded);
    6679           8 :                 return false;
    6680             :             }
    6681             :         }
    6682             :     }
    6683             : 
    6684        2866 :     free_var(&rounded);
    6685             : 
    6686        2866 :     if (!neg)
    6687             :     {
    6688        2734 :         if (unlikely(val == PG_INT64_MIN))
    6689          12 :             return false;
    6690        2722 :         val = -val;
    6691             :     }
    6692        2854 :     *result = val;
    6693             : 
    6694        2854 :     return true;
    6695             : }
    6696             : 
    6697             : /*
    6698             :  * Convert int8 value to numeric.
    6699             :  */
    6700             : static void
    6701      867520 : int64_to_numericvar(int64 val, NumericVar *var)
    6702             : {
    6703             :     uint64      uval,
    6704             :                 newuval;
    6705             :     NumericDigit *ptr;
    6706             :     int         ndigits;
    6707             : 
    6708             :     /* int64 can require at most 19 decimal digits; add one for safety */
    6709      867520 :     alloc_var(var, 20 / DEC_DIGITS);
    6710      867520 :     if (val < 0)
    6711             :     {
    6712         548 :         var->sign = NUMERIC_NEG;
    6713         548 :         uval = -val;
    6714             :     }
    6715             :     else
    6716             :     {
    6717      866972 :         var->sign = NUMERIC_POS;
    6718      866972 :         uval = val;
    6719             :     }
    6720      867520 :     var->dscale = 0;
    6721      867520 :     if (val == 0)
    6722             :     {
    6723       25758 :         var->ndigits = 0;
    6724       25758 :         var->weight = 0;
    6725       25758 :         return;
    6726             :     }
    6727      841762 :     ptr = var->digits + var->ndigits;
    6728      841762 :     ndigits = 0;
    6729             :     do
    6730             :     {
    6731      962700 :         ptr--;
    6732      962700 :         ndigits++;
    6733      962700 :         newuval = uval / NBASE;
    6734      962700 :         *ptr = uval - newuval * NBASE;
    6735      962700 :         uval = newuval;
    6736      962700 :     } while (uval);
    6737      841762 :     var->digits = ptr;
    6738      841762 :     var->ndigits = ndigits;
    6739      841762 :     var->weight = ndigits - 1;
    6740             : }
    6741             : 
    6742             : #ifdef HAVE_INT128
    6743             : /*
    6744             :  * Convert numeric to int128, rounding if needed.
    6745             :  *
    6746             :  * If overflow, return false (no error is raised).  Return true if okay.
    6747             :  */
    6748             : static bool
    6749          16 : numericvar_to_int128(const NumericVar *var, int128 *result)
    6750             : {
    6751             :     NumericDigit *digits;
    6752             :     int         ndigits;
    6753             :     int         weight;
    6754             :     int         i;
    6755             :     int128      val,
    6756             :                 oldval;
    6757             :     bool        neg;
    6758             :     NumericVar  rounded;
    6759             : 
    6760             :     /* Round to nearest integer */
    6761          80 :     init_var(&rounded);
    6762          16 :     set_var_from_var(var, &rounded);
    6763          16 :     round_var(&rounded, 0);
    6764             : 
    6765             :     /* Check for zero input */
    6766          16 :     strip_var(&rounded);
    6767          16 :     ndigits = rounded.ndigits;
    6768          16 :     if (ndigits == 0)
    6769             :     {
    6770           0 :         *result = 0;
    6771           0 :         free_var(&rounded);
    6772           0 :         return true;
    6773             :     }
    6774             : 
    6775             :     /*
    6776             :      * For input like 10000000000, we must treat stripped digits as real. So
    6777             :      * the loop assumes there are weight+1 digits before the decimal point.
    6778             :      */
    6779          16 :     weight = rounded.weight;
    6780             :     Assert(weight >= 0 && ndigits <= weight + 1);
    6781             : 
    6782             :     /* Construct the result */
    6783          16 :     digits = rounded.digits;
    6784          16 :     neg = (rounded.sign == NUMERIC_NEG);
    6785          16 :     val = digits[0];
    6786          36 :     for (i = 1; i <= weight; i++)
    6787             :     {
    6788          20 :         oldval = val;
    6789          20 :         val *= NBASE;
    6790          20 :         if (i < ndigits)
    6791          20 :             val += digits[i];
    6792             : 
    6793             :         /*
    6794             :          * The overflow check is a bit tricky because we want to accept
    6795             :          * INT128_MIN, which will overflow the positive accumulator.  We can
    6796             :          * detect this case easily though because INT128_MIN is the only
    6797             :          * nonzero value for which -val == val (on a two's complement machine,
    6798             :          * anyway).
    6799             :          */
    6800          20 :         if ((val / NBASE) != oldval)    /* possible overflow? */
    6801             :         {
    6802           0 :             if (!neg || (-val) != val || val == 0 || oldval < 0)
    6803             :             {
    6804           0 :                 free_var(&rounded);
    6805           0 :                 return false;
    6806             :             }
    6807             :         }
    6808             :     }
    6809             : 
    6810          16 :     free_var(&rounded);
    6811             : 
    6812          16 :     *result = neg ? -val : val;
    6813          16 :     return true;
    6814             : }
    6815             : 
    6816             : /*
    6817             :  * Convert 128 bit integer to numeric.
    6818             :  */
    6819             : static void
    6820        4902 : int128_to_numericvar(int128 val, NumericVar *var)
    6821             : {
    6822             :     uint128     uval,
    6823             :                 newuval;
    6824             :     NumericDigit *ptr;
    6825             :     int         ndigits;
    6826             : 
    6827             :     /* int128 can require at most 39 decimal digits; add one for safety */
    6828        4902 :     alloc_var(var, 40 / DEC_DIGITS);
    6829        4902 :     if (val < 0)
    6830             :     {
    6831           0 :         var->sign = NUMERIC_NEG;
    6832           0 :         uval = -val;
    6833             :     }
    6834             :     else
    6835             :     {
    6836        4902 :         var->sign = NUMERIC_POS;
    6837        4902 :         uval = val;
    6838             :     }
    6839        4902 :     var->dscale = 0;
    6840        4902 :     if (val == 0)
    6841             :     {
    6842          20 :         var->ndigits = 0;
    6843          20 :         var->weight = 0;
    6844          20 :         return;
    6845             :     }
    6846        4882 :     ptr = var->digits + var->ndigits;
    6847        4882 :     ndigits = 0;
    6848             :     do
    6849             :     {
    6850       26162 :         ptr--;
    6851       26162 :         ndigits++;
    6852       26162 :         newuval = uval / NBASE;
    6853       26162 :         *ptr = uval - newuval * NBASE;
    6854       26162 :         uval = newuval;
    6855       26162 :     } while (uval);
    6856        4882 :     var->digits = ptr;
    6857        4882 :     var->ndigits = ndigits;
    6858        4882 :     var->weight = ndigits - 1;
    6859             : }
    6860             : #endif
    6861             : 
    6862             : /*
    6863             :  * Convert numeric to float8; if out of range, return +/- HUGE_VAL
    6864             :  */
    6865             : static double
    6866        2910 : numeric_to_double_no_overflow(Numeric num)
    6867             : {
    6868             :     char       *tmp;
    6869             :     double      val;
    6870             :     char       *endptr;
    6871             : 
    6872        2910 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
    6873             :                                               NumericGetDatum(num)));
    6874             : 
    6875             :     /* unlike float8in, we ignore ERANGE from strtod */
    6876        2910 :     val = strtod(tmp, &endptr);
    6877        2910 :     if (*endptr != '\0')
    6878             :     {
    6879             :         /* shouldn't happen ... */
    6880           0 :         ereport(ERROR,
    6881             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    6882             :                  errmsg("invalid input syntax for type %s: \"%s\"",
    6883             :                         "double precision", tmp)));
    6884             :     }
    6885             : 
    6886        2910 :     pfree(tmp);
    6887             : 
    6888        2910 :     return val;
    6889             : }
    6890             : 
    6891             : /* As above, but work from a NumericVar */
    6892             : static double
    6893         160 : numericvar_to_double_no_overflow(const NumericVar *var)
    6894             : {
    6895             :     char       *tmp;
    6896             :     double      val;
    6897             :     char       *endptr;
    6898             : 
    6899         160 :     tmp = get_str_from_var(var);
    6900             : 
    6901             :     /* unlike float8in, we ignore ERANGE from strtod */
    6902         160 :     val = strtod(tmp, &endptr);
    6903         160 :     if (*endptr != '\0')
    6904             :     {
    6905             :         /* shouldn't happen ... */
    6906           0 :         ereport(ERROR,
    6907             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    6908             :                  errmsg("invalid input syntax for type %s: \"%s\"",
    6909             :                         "double precision", tmp)));
    6910             :     }
    6911             : 
    6912         160 :     pfree(tmp);
    6913             : 
    6914         160 :     return val;
    6915             : }
    6916             : 
    6917             : 
    6918             : /*
    6919             :  * cmp_var() -
    6920             :  *
    6921             :  *  Compare two values on variable level.  We assume zeroes have been
    6922             :  *  truncated to no digits.
    6923             :  */
    6924             : static int
    6925       10316 : cmp_var(const NumericVar *var1, const NumericVar *var2)
    6926             : {
    6927       30948 :     return cmp_var_common(var1->digits, var1->ndigits,
    6928             :                           var1->weight, var1->sign,
    6929       10316 :                           var2->digits, var2->ndigits,
    6930             :                           var2->weight, var2->sign);
    6931             : }
    6932             : 
    6933             : /*
    6934             :  * cmp_var_common() -
    6935             :  *
    6936             :  *  Main routine of cmp_var(). This function can be used by both
    6937             :  *  NumericVar and Numeric.
    6938             :  */
    6939             : static int
    6940     3603908 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
    6941             :                int var1weight, int var1sign,
    6942             :                const NumericDigit *var2digits, int var2ndigits,
    6943             :                int var2weight, int var2sign)
    6944             : {
    6945     3603908 :     if (var1ndigits == 0)
    6946             :     {
    6947      138702 :         if (var2ndigits == 0)
    6948      116912 :             return 0;
    6949       21790 :         if (var2sign == NUMERIC_NEG)
    6950        4590 :             return 1;
    6951       17200 :         return -1;
    6952             :     }
    6953     3465206 :     if (var2ndigits == 0)
    6954             :     {
    6955       27560 :         if (var1sign == NUMERIC_POS)
    6956       19930 :             return 1;
    6957        7630 :         return -1;
    6958             :     }
    6959             : 
    6960     3437646 :     if (var1sign == NUMERIC_POS)
    6961             :     {
    6962     3378964 :         if (var2sign == NUMERIC_NEG)
    6963       11392 :             return 1;
    6964     3367572 :         return cmp_abs_common(var1digits, var1ndigits, var1weight,
    6965             :                               var2digits, var2ndigits, var2weight);
    6966             :     }
    6967             : 
    6968       58682 :     if (var2sign == NUMERIC_POS)
    6969       12534 :         return -1;
    6970             : 
    6971       46148 :     return cmp_abs_common(var2digits, var2ndigits, var2weight,
    6972             :                           var1digits, var1ndigits, var1weight);
    6973             : }
    6974             : 
    6975             : 
    6976             : /*
    6977             :  * add_var() -
    6978             :  *
    6979             :  *  Full version of add functionality on variable level (handling signs).
    6980             :  *  result might point to one of the operands too without danger.
    6981             :  */
    6982             : static void
    6983      152350 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    6984             : {
    6985             :     /*
    6986             :      * Decide on the signs of the two variables what to do
    6987             :      */
    6988      152350 :     if (var1->sign == NUMERIC_POS)
    6989             :     {
    6990      151318 :         if (var2->sign == NUMERIC_POS)
    6991             :         {
    6992             :             /*
    6993             :              * Both are positive result = +(ABS(var1) + ABS(var2))
    6994             :              */
    6995       35950 :             add_abs(var1, var2, result);
    6996       35950 :             result->sign = NUMERIC_POS;
    6997             :         }
    6998             :         else
    6999             :         {
    7000             :             /*
    7001             :              * var1 is positive, var2 is negative Must compare absolute values
    7002             :              */
    7003      115368 :             switch (cmp_abs(var1, var2))
    7004             :             {
    7005           8 :                 case 0:
    7006             :                     /* ----------
    7007             :                      * ABS(var1) == ABS(var2)
    7008             :                      * result = ZERO
    7009             :                      * ----------
    7010             :                      */
    7011           8 :                     zero_var(result);
    7012           8 :                     result->dscale = Max(var1->dscale, var2->dscale);
    7013           8 :                     break;
    7014             : 
    7015      115172 :                 case 1:
    7016             :                     /* ----------
    7017             :                      * ABS(var1) > ABS(var2)
    7018             :                      * result = +(ABS(var1) - ABS(var2))
    7019             :                      * ----------
    7020             :                      */
    7021      115172 :                     sub_abs(var1, var2, result);
    7022      115172 :                     result->sign = NUMERIC_POS;
    7023      115172 :                     break;
    7024             : 
    7025         188 :                 case -1:
    7026             :                     /* ----------
    7027             :                      * ABS(var1) < ABS(var2)
    7028             :                      * result = -(ABS(var2) - ABS(var1))
    7029             :                      * ----------
    7030             :                      */
    7031         188 :                     sub_abs(var2, var1, result);
    7032         188 :                     result->sign = NUMERIC_NEG;
    7033         188 :                     break;
    7034             :             }
    7035      151318 :         }
    7036             :     }
    7037             :     else
    7038             :     {
    7039        1032 :         if (var2->sign == NUMERIC_POS)
    7040             :         {
    7041             :             /* ----------
    7042             :              * var1 is negative, var2 is positive
    7043             :              * Must compare absolute values
    7044             :              * ----------
    7045             :              */
    7046         304 :             switch (cmp_abs(var1, var2))
    7047             :             {
    7048          12 :                 case 0:
    7049             :                     /* ----------
    7050             :                      * ABS(var1) == ABS(var2)
    7051             :                      * result = ZERO
    7052             :                      * ----------
    7053             :                      */
    7054          12 :                     zero_var(result);
    7055          12 :                     result->dscale = Max(var1->dscale, var2->dscale);
    7056          12 :                     break;
    7057             : 
    7058         200 :                 case 1:
    7059             :                     /* ----------
    7060             :                      * ABS(var1) > ABS(var2)
    7061             :                      * result = -(ABS(var1) - ABS(var2))
    7062             :                      * ----------
    7063             :                      */
    7064         200 :                     sub_abs(var1, var2, result);
    7065         200 :                     result->sign = NUMERIC_NEG;
    7066         200 :                     break;
    7067             : 
    7068          92 :                 case -1:
    7069             :                     /* ----------
    7070             :                      * ABS(var1) < ABS(var2)
    7071             :                      * result = +(ABS(var2) - ABS(var1))
    7072             :                      * ----------
    7073             :                      */
    7074          92 :                     sub_abs(var2, var1, result);
    7075          92 :                     result->sign = NUMERIC_POS;
    7076          92 :                     break;
    7077             :             }
    7078         304 :         }
    7079             :         else
    7080             :         {
    7081             :             /* ----------
    7082             :              * Both are negative
    7083             :              * result = -(ABS(var1) + ABS(var2))
    7084             :              * ----------
    7085             :              */
    7086         728 :             add_abs(var1, var2, result);
    7087         728 :             result->sign = NUMERIC_NEG;
    7088             :         }
    7089             :     }
    7090      152350 : }
    7091             : 
    7092             : 
    7093             : /*
    7094             :  * sub_var() -
    7095             :  *
    7096             :  *  Full version of sub functionality on variable level (handling signs).
    7097             :  *  result might point to one of the operands too without danger.
    7098             :  */
    7099             : static void
    7100       42628 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    7101             : {
    7102             :     /*
    7103             :      * Decide on the signs of the two variables what to do
    7104             :      */
    7105       42628 :     if (var1->sign == NUMERIC_POS)
    7106             :     {
    7107       40238 :         if (var2->sign == NUMERIC_NEG)
    7108             :         {
    7109             :             /* ----------
    7110             :              * var1 is positive, var2 is negative
    7111             :              * result = +(ABS(var1) + ABS(var2))
    7112             :              * ----------
    7113             :              */
    7114        5806 :             add_abs(var1, var2, result);
    7115        5806 :             result->sign = NUMERIC_POS;
    7116             :         }
    7117             :         else
    7118             :         {
    7119             :             /* ----------
    7120             :              * Both are positive
    7121             :              * Must compare absolute values
    7122             :              * ----------
    7123             :              */
    7124       34432 :             switch (cmp_abs(var1, var2))
    7125             :             {
    7126       22394 :                 case 0:
    7127             :                     /* ----------
    7128             :                      * ABS(var1) == ABS(var2)
    7129             :                      * result = ZERO
    7130             :                      * ----------
    7131             :                      */
    7132       22394 :                     zero_var(result);
    7133       22394 :                     result->dscale = Max(var1->dscale, var2->dscale);
    7134       22394 :                     break;
    7135             : 
    7136       11732 :                 case 1:
    7137             :                     /* ----------
    7138             :                      * ABS(var1) > ABS(var2)
    7139             :                      * result = +(ABS(var1) - ABS(var2))
    7140             :                      * ----------
    7141             :                      */
    7142       11732 :                     sub_abs(var1, var2, result);
    7143       11732 :                     result->sign = NUMERIC_POS;
    7144       11732 :                     break;
    7145             : 
    7146         306 :                 case -1:
    7147             :                     /* ----------
    7148             :                      * ABS(var1) < ABS(var2)
    7149             :                      * result = -(ABS(var2) - ABS(var1))
    7150             :                      * ----------
    7151             :                      */
    7152         306 :                     sub_abs(var2, var1, result);
    7153         306 :                     result->sign = NUMERIC_NEG;
    7154         306 :                     break;
    7155             :             }
    7156       40238 :         }
    7157             :     }
    7158             :     else
    7159             :     {
    7160        2390 :         if (var2->sign == NUMERIC_NEG)
    7161             :         {
    7162             :             /* ----------
    7163             :              * Both are negative
    7164             :              * Must compare absolute values
    7165             :              * ----------
    7166             :              */
    7167        2134 :             switch (cmp_abs(var1, var2))
    7168             :             {
    7169         100 :                 case 0:
    7170             :                     /* ----------
    7171             :                      * ABS(var1) == ABS(var2)
    7172             :                      * result = ZERO
    7173             :                      * ----------
    7174             :                      */
    7175         100 :                     zero_var(result);
    7176         100 :                     result->dscale = Max(var1->dscale, var2->dscale);
    7177         100 :                     break;
    7178             : 
    7179         156 :                 case 1:
    7180             :                     /* ----------
    7181             :                      * ABS(var1) > ABS(var2)
    7182             :                      * result = -(ABS(var1) - ABS(var2))
    7183             :                      * ----------
    7184             :                      */
    7185         156 :                     sub_abs(var1, var2, result);
    7186         156 :                     result->sign = NUMERIC_NEG;
    7187         156 :                     break;
    7188             : 
    7189        1878 :                 case -1:
    7190             :                     /* ----------
    7191             :                      * ABS(var1) < ABS(var2)
    7192             :                      * result = +(ABS(var2) - ABS(var1))
    7193             :                      * ----------
    7194             :                      */
    7195        1878 :                     sub_abs(var2, var1, result);
    7196        1878 :                     result->sign = NUMERIC_POS;
    7197        1878 :                     break;
    7198             :             }
    7199        2134 :         }
    7200             :         else
    7201             :         {
    7202             :             /* ----------
    7203             :              * var1 is negative, var2 is positive
    7204             :              * result = -(ABS(var1) + ABS(var2))
    7205             :              * ----------
    7206             :              */
    7207         256 :             add_abs(var1, var2, result);
    7208         256 :             result->sign = NUMERIC_NEG;
    7209             :         }
    7210             :     }
    7211       42628 : }
    7212             : 
    7213             : 
    7214             : /*
    7215             :  * mul_var() -
    7216             :  *
    7217             :  *  Multiplication on variable level. Product of var1 * var2 is stored
    7218             :  *  in result.  Result is rounded to no more than rscale fractional digits.
    7219             :  */
    7220             : static void
    7221      348844 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
    7222             :         int rscale)
    7223             : {
    7224             :     int         res_ndigits;
    7225             :     int         res_sign;
    7226             :     int         res_weight;
    7227             :     int         maxdigits;
    7228             :     int        *dig;
    7229             :     int         carry;
    7230             :     int         maxdig;
    7231             :     int         newdig;
    7232             :     int         var1ndigits;
    7233             :     int         var2ndigits;
    7234             :     NumericDigit *var1digits;
    7235             :     NumericDigit *var2digits;
    7236             :     NumericDigit *res_digits;
    7237             :     int         i,
    7238             :                 i1,
    7239             :                 i2;
    7240             : 
    7241             :     /*
    7242             :      * Arrange for var1 to be the shorter of the two numbers.  This improves
    7243             :      * performance because the inner multiplication loop is much simpler than
    7244             :      * the outer loop, so it's better to have a smaller number of iterations
    7245             :      * of the outer loop.  This also reduces the number of times that the
    7246             :      * accumulator array needs to be normalized.
    7247             :      */
    7248      348844 :     if (var1->ndigits > var2->ndigits)
    7249             :     {
    7250        5400 :         const NumericVar *tmp = var1;
    7251             : 
    7252        5400 :         var1 = var2;
    7253        5400 :         var2 = tmp;
    7254             :     }
    7255             : 
    7256             :     /* copy these values into local vars for speed in inner loop */
    7257      348844 :     var1ndigits = var1->ndigits;
    7258      348844 :     var2ndigits = var2->ndigits;
    7259      348844 :     var1digits = var1->digits;
    7260      348844 :     var2digits = var2->digits;
    7261             : 
    7262      348844 :     if (var1ndigits == 0 || var2ndigits == 0)
    7263             :     {
    7264             :         /* one or both inputs is zero; so is result */
    7265         384 :         zero_var(result);
    7266         384 :         result->dscale = rscale;
    7267         384 :         return;
    7268             :     }
    7269             : 
    7270             :     /* Determine result sign and (maximum possible) weight */
    7271      348460 :     if (var1->sign == var2->sign)
    7272      347084 :         res_sign = NUMERIC_POS;
    7273             :     else
    7274        1376 :         res_sign = NUMERIC_NEG;
    7275      348460 :     res_weight = var1->weight + var2->weight + 2;
    7276             : 
    7277             :     /*
    7278             :      * Determine the number of result digits to compute.  If the exact result
    7279             :      * would have more than rscale fractional digits, truncate the computation
    7280             :      * with MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that
    7281             :      * would only contribute to the right of that.  (This will give the exact
    7282             :      * rounded-to-rscale answer unless carries out of the ignored positions
    7283             :      * would have propagated through more than MUL_GUARD_DIGITS digits.)
    7284             :      *
    7285             :      * Note: an exact computation could not produce more than var1ndigits +
    7286             :      * var2ndigits digits, but we allocate one extra output digit in case
    7287             :      * rscale-driven rounding produces a carry out of the highest exact digit.
    7288             :      */
    7289      348460 :     res_ndigits = var1ndigits + var2ndigits + 1;
    7290      348460 :     maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
    7291             :         MUL_GUARD_DIGITS;
    7292      348460 :     res_ndigits = Min(res_ndigits, maxdigits);
    7293             : 
    7294      348460 :     if (res_ndigits < 3)
    7295             :     {
    7296             :         /* All input digits will be ignored; so result is zero */
    7297           0 :         zero_var(result);
    7298           0 :         result->dscale = rscale;
    7299           0 :         return;
    7300             :     }
    7301             : 
    7302             :     /*
    7303             :      * We do the arithmetic in an array "dig[]" of signed int's.  Since
    7304             :      * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
    7305             :      * to avoid normalizing carries immediately.
    7306             :      *
    7307             :      * maxdig tracks the maximum possible value of any dig[] entry; when this
    7308             :      * threatens to exceed INT_MAX, we take the time to propagate carries.
    7309             :      * Furthermore, we need to ensure that overflow doesn't occur during the
    7310             :      * carry propagation passes either.  The carry values could be as much as
    7311             :      * INT_MAX/NBASE, so really we must normalize when digits threaten to
    7312             :      * exceed INT_MAX - INT_MAX/NBASE.
    7313             :      *
    7314             :      * To avoid overflow in maxdig itself, it actually represents the max
    7315             :      * possible value divided by NBASE-1, ie, at the top of the loop it is
    7316             :      * known that no dig[] entry exceeds maxdig * (NBASE-1).
    7317             :      */
    7318      348460 :     dig = (int *) palloc0(res_ndigits * sizeof(int));
    7319      348460 :     maxdig = 0;
    7320             : 
    7321             :     /*
    7322             :      * The least significant digits of var1 should be ignored if they don't
    7323             :      * contribute directly to the first res_ndigits digits of the result that
    7324             :      * we are computing.
    7325             :      *
    7326             :      * Digit i1 of var1 and digit i2 of var2 are multiplied and added to digit
    7327             :      * i1+i2+2 of the accumulator array, so we need only consider digits of
    7328             :      * var1 for which i1 <= res_ndigits - 3.
    7329             :      */
    7330     1017528 :     for (i1 = Min(var1ndigits - 1, res_ndigits - 3); i1 >= 0; i1--)
    7331             :     {
    7332      669068 :         int         var1digit = var1digits[i1];
    7333             : 
    7334      669068 :         if (var1digit == 0)
    7335          20 :             continue;
    7336             : 
    7337             :         /* Time to normalize? */
    7338      669048 :         maxdig += var1digit;
    7339      669048 :         if (maxdig > (INT_MAX - INT_MAX / NBASE) / (NBASE - 1))
    7340             :         {
    7341             :             /* Yes, do it */
    7342        2296 :             carry = 0;
    7343      153456 :             for (i = res_ndigits - 1; i >= 0; i--)
    7344             :             {
    7345      151160 :                 newdig = dig[i] + carry;
    7346      151160 :                 if (newdig >= NBASE)
    7347             :                 {
    7348      111208 :                     carry = newdig / NBASE;
    7349      111208 :                     newdig -= carry * NBASE;
    7350             :                 }
    7351             :                 else
    7352       39952 :                     carry = 0;
    7353      151160 :                 dig[i] = newdig;
    7354             :             }
    7355             :             Assert(carry == 0);
    7356             :             /* Reset maxdig to indicate new worst-case */
    7357        2296 :             maxdig = 1 + var1digit;
    7358             :         }
    7359             : 
    7360             :         /*
    7361             :          * Add the appropriate multiple of var2 into the accumulator.
    7362             :          *
    7363             :          * As above, digits of var2 can be ignored if they don't contribute,
    7364             :          * so we only include digits for which i1+i2+2 <= res_ndigits - 1.
    7365             :          */
    7366     8638500 :         for (i2 = Min(var2ndigits - 1, res_ndigits - i1 - 3), i = i1 + i2 + 2;
    7367     7969452 :              i2 >= 0; i2--)
    7368     7969452 :             dig[i--] += var1digit * var2digits[i2];
    7369             :     }
    7370             : 
    7371             :     /*
    7372             :      * Now we do a final carry propagation pass to normalize the result, which
    7373             :      * we combine with storing the result digits into the output. Note that
    7374             :      * this is still done at full precision w/guard digits.
    7375             :      */
    7376      348460 :     alloc_var(result, res_ndigits);
    7377      348460 :     res_digits = result->digits;
    7378      348460 :     carry = 0;
    7379     2097816 :     for (i = res_ndigits - 1; i >= 0; i--)
    7380             :     {
    7381     1749356 :         newdig = dig[i] + carry;
    7382     1749356 :         if (newdig >= NBASE)
    7383             :         {
    7384     1031852 :             carry = newdig / NBASE;
    7385     1031852 :             newdig -= carry * NBASE;
    7386             :         }
    7387             :         else
    7388      717504 :             carry = 0;
    7389     1749356 :         res_digits[i] = newdig;
    7390             :     }
    7391             :     Assert(carry == 0);
    7392             : 
    7393      348460 :     pfree(dig);
    7394             : 
    7395             :     /*
    7396             :      * Finally, round the result to the requested precision.
    7397             :      */
    7398      348460 :     result->weight = res_weight;
    7399      348460 :     result->sign = res_sign;
    7400             : 
    7401             :     /* Round to target rscale (and set result->dscale) */
    7402      348460 :     round_var(result, rscale);
    7403             : 
    7404             :     /* Strip leading and trailing zeroes */
    7405      348460 :     strip_var(result);
    7406             : }
    7407             : 
    7408             : 
    7409             : /*
    7410             :  * div_var() -
    7411             :  *
    7412             :  *  Division on variable level. Quotient of var1 / var2 is stored in result.
    7413             :  *  The quotient is figured to exactly rscale fractional digits.
    7414             :  *  If round is true, it is rounded at the rscale'th digit; if false, it
    7415             :  *  is truncated (towards zero) at that digit.
    7416             :  */
    7417             : static void
    7418       74084 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
    7419             :         int rscale, bool round)
    7420             : {
    7421             :     int         div_ndigits;
    7422             :     int         res_ndigits;
    7423             :     int         res_sign;
    7424             :     int         res_weight;
    7425             :     int         carry;
    7426             :     int         borrow;
    7427             :     int         divisor1;
    7428             :     int         divisor2;
    7429             :     NumericDigit *dividend;
    7430             :     NumericDigit *divisor;
    7431             :     NumericDigit *res_digits;
    7432             :     int         i;
    7433             :     int         j;
    7434             : 
    7435             :     /* copy these values into local vars for speed in inner loop */
    7436       74084 :     int         var1ndigits = var1->ndigits;
    7437       74084 :     int         var2ndigits = var2->ndigits;
    7438             : 
    7439             :     /*
    7440             :      * First of all division by zero check; we must not be handed an
    7441             :      * unnormalized divisor.
    7442             :      */
    7443       74084 :     if (var2ndigits == 0 || var2->digits[0] == 0)
    7444          24 :         ereport(ERROR,
    7445             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    7446             :                  errmsg("division by zero")));
    7447             : 
    7448             :     /*
    7449             :      * Now result zero check
    7450             :      */
    7451       74060 :     if (var1ndigits == 0)
    7452             :     {
    7453        1106 :         zero_var(result);
    7454        1106 :         result->dscale = rscale;
    7455        1106 :         return;
    7456             :     }
    7457             : 
    7458             :     /*
    7459             :      * Determine the result sign, weight and number of digits to calculate.
    7460             :      * The weight figured here is correct if the emitted quotient has no
    7461             :      * leading zero digits; otherwise strip_var() will fix things up.
    7462             :      */
    7463       72954 :     if (var1->sign == var2->sign)
    7464       71934 :         res_sign = NUMERIC_POS;
    7465             :     else
    7466        1020 :         res_sign = NUMERIC_NEG;
    7467       72954 :     res_weight = var1->weight - var2->weight;
    7468             :     /* The number of accurate result digits we need to produce: */
    7469       72954 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
    7470             :     /* ... but always at least 1 */
    7471       72954 :     res_ndigits = Max(res_ndigits, 1);
    7472             :     /* If rounding needed, figure one more digit to ensure correct result */
    7473       72954 :     if (round)
    7474       72190 :         res_ndigits++;
    7475             : 
    7476             :     /*
    7477             :      * The working dividend normally requires res_ndigits + var2ndigits
    7478             :      * digits, but make it at least var1ndigits so we can load all of var1
    7479             :      * into it.  (There will be an additional digit dividend[0] in the
    7480             :      * dividend space, but for consistency with Knuth's notation we don't
    7481             :      * count that in div_ndigits.)
    7482             :      */
    7483       72954 :     div_ndigits = res_ndigits + var2ndigits;
    7484       72954 :     div_ndigits = Max(div_ndigits, var1ndigits);
    7485             : 
    7486             :     /*
    7487             :      * We need a workspace with room for the working dividend (div_ndigits+1
    7488             :      * digits) plus room for the possibly-normalized divisor (var2ndigits
    7489             :      * digits).  It is convenient also to have a zero at divisor[0] with the
    7490             :      * actual divisor data in divisor[1 .. var2ndigits].  Transferring the
    7491             :      * digits into the workspace also allows us to realloc the result (which
    7492             :      * might be the same as either input var) before we begin the main loop.
    7493             :      * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
    7494             :      * any additional dividend positions beyond var1ndigits, start out 0.
    7495             :      */
    7496             :     dividend = (NumericDigit *)
    7497       72954 :         palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
    7498       72954 :     divisor = dividend + (div_ndigits + 1);
    7499       72954 :     memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
    7500       72954 :     memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
    7501             : 
    7502             :     /*
    7503             :      * Now we can realloc the result to hold the generated quotient digits.
    7504             :      */
    7505       72954 :     alloc_var(result, res_ndigits);
    7506       72954 :     res_digits = result->digits;
    7507             : 
    7508       72954 :     if (var2ndigits == 1)
    7509             :     {
    7510             :         /*
    7511             :          * If there's only a single divisor digit, we can use a fast path (cf.
    7512             :          * Knuth section 4.3.1 exercise 16).
    7513             :          */
    7514       69208 :         divisor1 = divisor[1];
    7515       69208 :         carry = 0;
    7516      808458 :         for (i = 0; i < res_ndigits; i++)
    7517             :         {
    7518      739250 :             carry = carry * NBASE + dividend[i + 1];
    7519      739250 :             res_digits[i] = carry / divisor1;
    7520      739250 :             carry = carry % divisor1;
    7521             :         }
    7522             :     }
    7523             :     else
    7524             :     {
    7525             :         /*
    7526             :          * The full multiple-place algorithm is taken from Knuth volume 2,
    7527             :          * Algorithm 4.3.1D.
    7528             :          *
    7529             :          * We need the first divisor digit to be >= NBASE/2.  If it isn't,
    7530             :          * make it so by scaling up both the divisor and dividend by the
    7531             :          * factor "d".  (The reason for allocating dividend[0] above is to
    7532             :          * leave room for possible carry here.)
    7533             :          */
    7534        3746 :         if (divisor[1] < HALF_NBASE)
    7535             :         {
    7536        3682 :             int         d = NBASE / (divisor[1] + 1);
    7537             : 
    7538        3682 :             carry = 0;
    7539       27748 :             for (i = var2ndigits; i > 0; i--)
    7540             :             {
    7541       24066 :                 carry += divisor[i] * d;
    7542       24066 :                 divisor[i] = carry % NBASE;
    7543       24066 :                 carry = carry / NBASE;
    7544             :             }
    7545             :             Assert(carry == 0);
    7546        3682 :             carry = 0;
    7547             :             /* at this point only var1ndigits of dividend can be nonzero */
    7548       29634 :             for (i = var1ndigits; i >= 0; i--)
    7549             :             {
    7550       25952 :                 carry += dividend[i] * d;
    7551       25952 :                 dividend[i] = carry % NBASE;
    7552       25952 :                 carry = carry / NBASE;
    7553             :             }
    7554             :             Assert(carry == 0);
    7555             :             Assert(divisor[1] >= HALF_NBASE);
    7556             :         }
    7557             :         /* First 2 divisor digits are used repeatedly in main loop */
    7558        3746 :         divisor1 = divisor[1];
    7559        3746 :         divisor2 = divisor[2];
    7560             : 
    7561             :         /*
    7562             :          * Begin the main loop.  Each iteration of this loop produces the j'th
    7563             :          * quotient digit by dividing dividend[j .. j + var2ndigits] by the
    7564             :          * divisor; this is essentially the same as the common manual
    7565             :          * procedure for long division.
    7566             :          */
    7567       27374 :         for (j = 0; j < res_ndigits; j++)
    7568             :         {
    7569             :             /* Estimate quotient digit from the first two dividend digits */
    7570       23628 :             int         next2digits = dividend[j] * NBASE + dividend[j + 1];
    7571             :             int         qhat;
    7572             : 
    7573             :             /*
    7574             :              * If next2digits are 0, then quotient digit must be 0 and there's
    7575             :              * no need to adjust the working dividend.  It's worth testing
    7576             :              * here to fall out ASAP when processing trailing zeroes in a
    7577             :              * dividend.
    7578             :              */
    7579       23628 :             if (next2digits == 0)
    7580             :             {
    7581         384 :                 res_digits[j] = 0;
    7582         384 :                 continue;
    7583             :             }
    7584             : 
    7585       23244 :             if (dividend[j] == divisor1)
    7586         120 :                 qhat = NBASE - 1;
    7587             :             else
    7588       23124 :                 qhat = next2digits / divisor1;
    7589             : 
    7590             :             /*
    7591             :              * Adjust quotient digit if it's too large.  Knuth proves that
    7592             :              * after this step, the quotient digit will be either correct or
    7593             :              * just one too large.  (Note: it's OK to use dividend[j+2] here
    7594             :              * because we know the divisor length is at least 2.)
    7595             :              */
    7596       23244 :             while (divisor2 * qhat >
    7597       27010 :                    (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
    7598        3766 :                 qhat--;
    7599             : 
    7600             :             /* As above, need do nothing more when quotient digit is 0 */
    7601       23244 :             if (qhat > 0)
    7602             :             {
    7603             :                 /*
    7604             :                  * Multiply the divisor by qhat, and subtract that from the
    7605             :                  * working dividend.  "carry" tracks the multiplication,
    7606             :                  * "borrow" the subtraction (could we fold these together?)
    7607             :                  */
    7608       20564 :                 carry = 0;
    7609       20564 :                 borrow = 0;
    7610      187824 :                 for (i = var2ndigits; i >= 0; i--)
    7611             :                 {
    7612      167260 :                     carry += divisor[i] * qhat;
    7613      167260 :                     borrow -= carry % NBASE;
    7614      167260 :                     carry = carry / NBASE;
    7615      167260 :                     borrow += dividend[j + i];
    7616      167260 :                     if (borrow < 0)
    7617             :                     {
    7618       84342 :                         dividend[j + i] = borrow + NBASE;
    7619       84342 :                         borrow = -1;
    7620             :                     }
    7621             :                     else
    7622             :                     {
    7623       82918 :                         dividend[j + i] = borrow;
    7624       82918 :                         borrow = 0;
    7625             :                     }
    7626             :                 }
    7627             :                 Assert(carry == 0);
    7628             : 
    7629             :                 /*
    7630             :                  * If we got a borrow out of the top dividend digit, then
    7631             :                  * indeed qhat was one too large.  Fix it, and add back the
    7632             :                  * divisor to correct the working dividend.  (Knuth proves
    7633             :                  * that this will occur only about 3/NBASE of the time; hence,
    7634             :                  * it's a good idea to test this code with small NBASE to be
    7635             :                  * sure this section gets exercised.)
    7636             :                  */
    7637       20564 :                 if (borrow)
    7638             :                 {
    7639          20 :                     qhat--;
    7640          20 :                     carry = 0;
    7641        2140 :                     for (i = var2ndigits; i >= 0; i--)
    7642             :                     {
    7643        2120 :                         carry += dividend[j + i] + divisor[i];
    7644        2120 :                         if (carry >= NBASE)
    7645             :                         {
    7646        2082 :                             dividend[j + i] = carry - NBASE;
    7647        2082 :                             carry = 1;
    7648             :                         }
    7649             :                         else
    7650             :                         {
    7651          38 :                             dividend[j + i] = carry;
    7652          38 :                             carry = 0;
    7653             :                         }
    7654             :                     }
    7655             :                     /* A carry should occur here to cancel the borrow above */
    7656             :                     Assert(carry == 1);
    7657             :                 }
    7658             :             }
    7659             : 
    7660             :             /* And we're done with this quotient digit */
    7661       23244 :             res_digits[j] = qhat;
    7662             :         }
    7663             :     }
    7664             : 
    7665       72954 :     pfree(dividend);
    7666             : 
    7667             :     /*
    7668             :      * Finally, round or truncate the result to the requested precision.
    7669             :      */
    7670       72954 :     result->weight = res_weight;
    7671       72954 :     result->sign = res_sign;
    7672             : 
    7673             :     /* Round or truncate to target rscale (and set result->dscale) */
    7674       72954 :     if (round)
    7675       72190 :         round_var(result, rscale);
    7676             :     else
    7677         764 :         trunc_var(result, rscale);
    7678             : 
    7679             :     /* Strip leading and trailing zeroes */
    7680       72954 :     strip_var(result);
    7681             : }
    7682             : 
    7683             : 
    7684             : /*
    7685             :  * div_var_fast() -
    7686             :  *
    7687             :  *  This has the same API as div_var, but is implemented using the division
    7688             :  *  algorithm from the "FM" library, rather than Knuth's schoolbook-division
    7689             :  *  approach.  This is significantly faster but can produce inaccurate
    7690             :  *  results, because it sometimes has to propagate rounding to the left,
    7691             :  *  and so we can never be entirely sure that we know the requested digits
    7692             :  *  exactly.  We compute DIV_GUARD_DIGITS extra digits, but there is
    7693             :  *  no certainty that that's enough.  We use this only in the transcendental
    7694             :  *  function calculation routines, where everything is approximate anyway.
    7695             :  *
    7696             :  *  Although we provide a "round" argument for consistency with div_var,
    7697             :  *  it is unwise to use this function with round=false.  In truncation mode
    7698             :  *  it is possible to get a result with no significant digits, for example
    7699             :  *  with rscale=0 we might compute 0.99999... and truncate that to 0 when
    7700             :  *  the correct answer is 1.
    7701             :  */
    7702             : static void
    7703       14796 : div_var_fast(const NumericVar *var1, const NumericVar *var2,
    7704             :              NumericVar *result, int rscale, bool round)
    7705             : {
    7706             :     int         div_ndigits;
    7707             :     int         load_ndigits;
    7708             :     int         res_sign;
    7709             :     int         res_weight;
    7710             :     int        *div;
    7711             :     int         qdigit;
    7712             :     int         carry;
    7713             :     int         maxdiv;
    7714             :     int         newdig;
    7715             :     NumericDigit *res_digits;
    7716             :     double      fdividend,
    7717             :                 fdivisor,
    7718             :                 fdivisorinverse,
    7719             :                 fquotient;
    7720             :     int         qi;
    7721             :     int         i;
    7722             : 
    7723             :     /* copy these values into local vars for speed in inner loop */
    7724       14796 :     int         var1ndigits = var1->ndigits;
    7725       14796 :     int         var2ndigits = var2->ndigits;
    7726       14796 :     NumericDigit *var1digits = var1->digits;
    7727       14796 :     NumericDigit *var2digits = var2->digits;
    7728             : 
    7729             :     /*
    7730             :      * First of all division by zero check; we must not be handed an
    7731             :      * unnormalized divisor.
    7732             :      */
    7733       14796 :     if (var2ndigits == 0 || var2digits[0] == 0)
    7734           4 :         ereport(ERROR,
    7735             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    7736             :                  errmsg("division by zero")));
    7737             : 
    7738             :     /*
    7739             :      * Now result zero check
    7740             :      */
    7741       14792 :     if (var1ndigits == 0)
    7742             :     {
    7743         228 :         zero_var(result);
    7744         228 :         result->dscale = rscale;
    7745         228 :         return;
    7746             :     }
    7747             : 
    7748             :     /*
    7749             :      * Determine the result sign, weight and number of digits to calculate
    7750             :      */
    7751       14564 :     if (var1->sign == var2->sign)
    7752       13772 :         res_sign = NUMERIC_POS;
    7753             :     else
    7754         792 :         res_sign = NUMERIC_NEG;
    7755       14564 :     res_weight = var1->weight - var2->weight + 1;
    7756             :     /* The number of accurate result digits we need to produce: */
    7757       14564 :     div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
    7758             :     /* Add guard digits for roundoff error */
    7759       14564 :     div_ndigits += DIV_GUARD_DIGITS;
    7760       14564 :     if (div_ndigits < DIV_GUARD_DIGITS)
    7761           0 :         div_ndigits = DIV_GUARD_DIGITS;
    7762             : 
    7763             :     /*
    7764             :      * We do the arithmetic in an array "div[]" of signed int's.  Since
    7765             :      * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
    7766             :      * to avoid normalizing carries immediately.
    7767             :      *
    7768             :      * We start with div[] containing one zero digit followed by the
    7769             :      * dividend's digits (plus appended zeroes to reach the desired precision
    7770             :      * including guard digits).  Each step of the main loop computes an
    7771             :      * (approximate) quotient digit and stores it into div[], removing one
    7772             :      * position of dividend space.  A final pass of carry propagation takes
    7773             :      * care of any mistaken quotient digits.
    7774             :      *
    7775             :      * Note that div[] doesn't necessarily contain all of the digits from the
    7776             :      * dividend --- the desired precision plus guard digits might be less than
    7777             :      * the dividend's precision.  This happens, for example, in the square
    7778             :      * root algorithm, where we typically divide a 2N-digit number by an
    7779             :      * N-digit number, and only require a result with N digits of precision.
    7780             :      */
    7781       14564 :     div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
    7782       14564 :     load_ndigits = Min(div_ndigits, var1ndigits);
    7783      321808 :     for (i = 0; i < load_ndigits; i++)
    7784      307244 :         div[i + 1] = var1digits[i];
    7785             : 
    7786             :     /*
    7787             :      * We estimate each quotient digit using floating-point arithmetic, taking
    7788             :      * the first four digits of the (current) dividend and divisor.  This must
    7789             :      * be float to avoid overflow.  The quotient digits will generally be off
    7790             :      * by no more than one from the exact answer.
    7791             :      */
    7792       14564 :     fdivisor = (double) var2digits[0];
    7793       58256 :     for (i = 1; i < 4; i++)
    7794             :     {
    7795       43692 :         fdivisor *= NBASE;
    7796       43692 :         if (i < var2ndigits)
    7797        9548 :             fdivisor += (double) var2digits[i];
    7798             :     }
    7799       14564 :     fdivisorinverse = 1.0 / fdivisor;
    7800             : 
    7801             :     /*
    7802             :      * maxdiv tracks the maximum possible absolute value of any div[] entry;
    7803             :      * when this threatens to exceed INT_MAX, we take the time to propagate
    7804             :      * carries.  Furthermore, we need to ensure that overflow doesn't occur
    7805             :      * during the carry propagation passes either.  The carry values may have
    7806             :      * an absolute value as high as INT_MAX/NBASE + 1, so really we must
    7807             :      * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
    7808             :      *
    7809             :      * To avoid overflow in maxdiv itself, it represents the max absolute
    7810             :      * value divided by NBASE-1, ie, at the top of the loop it is known that
    7811             :      * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
    7812             :      *
    7813             :      * Actually, though, that holds good only for div[] entries after div[qi];
    7814             :      * the adjustment done at the bottom of the loop may cause div[qi + 1] to
    7815             :      * exceed the maxdiv limit, so that div[qi] in the next iteration is
    7816             :      * beyond the limit.  This does not cause problems, as explained below.
    7817             :      */
    7818       14564 :     maxdiv = 1;
    7819             : 
    7820             :     /*
    7821             :      * Outer loop computes next quotient digit, which will go into div[qi]
    7822             :      */
    7823      392532 :     for (qi = 0; qi < div_ndigits; qi++)
    7824             :     {
    7825             :         /* Approximate the current dividend value */
    7826      377968 :         fdividend = (double) div[qi];
    7827     1511872 :         for (i = 1; i < 4; i++)
    7828             :         {
    7829     1133904 :             fdividend *= NBASE;
    7830     1133904 :             if (qi + i <= div_ndigits)
    7831     1090212 :                 fdividend += (double) div[qi + i];
    7832             :         }
    7833             :         /* Compute the (approximate) quotient digit */
    7834      377968 :         fquotient = fdividend * fdivisorinverse;
    7835      377968 :         qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
    7836           4 :             (((int) fquotient) - 1);    /* truncate towards -infinity */
    7837             : 
    7838      377968 :         if (qdigit != 0)
    7839             :         {
    7840             :             /* Do we need to normalize now? */
    7841      346312 :             maxdiv += Abs(qdigit);
    7842      346312 :             if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
    7843             :             {
    7844             :                 /*
    7845             :                  * Yes, do it.  Note that if var2ndigits is much smaller than
    7846             :                  * div_ndigits, we can save a significant amount of effort
    7847             :                  * here by noting that we only need to normalise those div[]
    7848             :                  * entries touched where prior iterations subtracted multiples
    7849             :                  * of the divisor.
    7850             :                  */
    7851        2656 :                 carry = 0;
    7852        3856 :                 for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
    7853             :                 {
    7854        1200 :                     newdig = div[i] + carry;
    7855        1200 :                     if (newdig < 0)
    7856             :                     {
    7857        1200 :                         carry = -((-newdig - 1) / NBASE) - 1;
    7858        1200 :                         newdig -= carry * NBASE;
    7859             :                     }
    7860           0 :                     else if (newdig >= NBASE)
    7861             :                     {
    7862           0 :                         carry = newdig / NBASE;
    7863           0 :                         newdig -= carry * NBASE;
    7864             :                     }
    7865             :                     else
    7866           0 :                         carry = 0;
    7867        1200 :                     div[i] = newdig;
    7868             :                 }
    7869        2656 :                 newdig = div[qi] + carry;
    7870        2656 :                 div[qi] = newdig;
    7871             : 
    7872             :                 /*
    7873             :                  * All the div[] digits except possibly div[qi] are now in the
    7874             :                  * range 0..NBASE-1.  We do not need to consider div[qi] in
    7875             :                  * the maxdiv value anymore, so we can reset maxdiv to 1.
    7876             :                  */
    7877        2656 :                 maxdiv = 1;
    7878             : 
    7879             :                 /*
    7880             :                  * Recompute the quotient digit since new info may have
    7881             :                  * propagated into the top four dividend digits
    7882             :                  */
    7883        2656 :                 fdividend = (double) div[qi];
    7884       10624 :                 for (i = 1; i < 4; i++)
    7885             :                 {
    7886        7968 :                     fdividend *= NBASE;
    7887        7968 :                     if (qi + i <= div_ndigits)
    7888        7680 :                         fdividend += (double) div[qi + i];
    7889             :                 }
    7890             :                 /* Compute the (approximate) quotient digit */
    7891        2656 :                 fquotient = fdividend * fdivisorinverse;
    7892        2656 :                 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
    7893           0 :                     (((int) fquotient) - 1);    /* truncate towards -infinity */
    7894        2656 :                 maxdiv += Abs(qdigit);
    7895             :             }
    7896             : 
    7897             :             /*
    7898             :              * Subtract off the appropriate multiple of the divisor.
    7899             :              *
    7900             :              * The digits beyond div[qi] cannot overflow, because we know they
    7901             :              * will fall within the maxdiv limit.  As for div[qi] itself, note
    7902             :              * that qdigit is approximately trunc(div[qi] / vardigits[0]),
    7903             :              * which would make the new value simply div[qi] mod vardigits[0].
    7904             :              * The lower-order terms in qdigit can change this result by not
    7905             :              * more than about twice INT_MAX/NBASE, so overflow is impossible.
    7906             :              */
    7907      346312 :             if (qdigit != 0)
    7908             :             {
    7909      346312 :                 int         istop = Min(var2ndigits, div_ndigits - qi + 1);
    7910             : 
    7911     1197388 :                 for (i = 0; i < istop; i++)
    7912      851076 :                     div[qi + i] -= qdigit * var2digits[i];
    7913             :             }
    7914             :         }
    7915             : 
    7916             :         /*
    7917             :          * The dividend digit we are about to replace might still be nonzero.
    7918             :          * Fold it into the next digit position.
    7919             :          *
    7920             :          * There is no risk of overflow here, although proving that requires
    7921             :          * some care.  Much as with the argument for div[qi] not overflowing,
    7922             :          * if we consider the first two terms in the numerator and denominator
    7923             :          * of qdigit, we can see that the final value of div[qi + 1] will be
    7924             :          * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
    7925             :          * Accounting for the lower-order terms is a bit complicated but ends
    7926             :          * up adding not much more than INT_MAX/NBASE to the possible range.
    7927             :          * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
    7928             :          * in the next loop iteration, it can't be large enough to cause
    7929             :          * overflow in the carry propagation step (if any), either.
    7930             :          *
    7931             :          * But having said that: div[qi] can be more than INT_MAX/NBASE, as
    7932             :          * noted above, which means that the product div[qi] * NBASE *can*
    7933             :          * overflow.  When that happens, adding it to div[qi + 1] will always
    7934             :          * cause a canceling overflow so that the end result is correct.  We
    7935             :          * could avoid the intermediate overflow by doing the multiplication
    7936             :          * and addition in int64 arithmetic, but so far there appears no need.
    7937             :          */
    7938      377968 :         div[qi + 1] += div[qi] * NBASE;
    7939             : 
    7940      377968 :         div[qi] = qdigit;
    7941             :     }
    7942             : 
    7943             :     /*
    7944             :      * Approximate and store the last quotient digit (div[div_ndigits])
    7945             :      */
    7946       14564 :     fdividend = (double) div[qi];
    7947       58256 :     for (i = 1; i < 4; i++)
    7948       43692 :         fdividend *= NBASE;
    7949       14564 :     fquotient = fdividend * fdivisorinverse;
    7950       14564 :     qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
    7951           0 :         (((int) fquotient) - 1);    /* truncate towards -infinity */
    7952       14564 :     div[qi] = qdigit;
    7953             : 
    7954             :     /*
    7955             :      * Because the quotient digits might be off by one, some of them might be
    7956             :      * -1 or NBASE at this point.  The represented value is correct in a
    7957             :      * mathematical sense, but it doesn't look right.  We do a final carry
    7958             :      * propagation pass to normalize the digits, which we combine with storing
    7959             :      * the result digits into the output.  Note that this is still done at
    7960             :      * full precision w/guard digits.
    7961             :      */
    7962       14564 :     alloc_var(result, div_ndigits + 1);
    7963       14564 :     res_digits = result->digits;
    7964       14564 :     carry = 0;
    7965      407096 :     for (i = div_ndigits; i >= 0; i--)
    7966             :     {
    7967      392532 :         newdig = div[i] + carry;
    7968      392532 :         if (newdig < 0)
    7969             :         {
    7970           8 :             carry = -((-newdig - 1) / NBASE) - 1;
    7971           8 :             newdig -= carry * NBASE;
    7972             :         }
    7973      392524 :         else if (newdig >= NBASE)
    7974             :         {
    7975         220 :             carry = newdig / NBASE;
    7976         220 :             newdig -= carry * NBASE;
    7977             :         }
    7978             :         else
    7979      392304 :             carry = 0;
    7980      392532 :         res_digits[i] = newdig;
    7981             :     }
    7982             :     Assert(carry == 0);
    7983             : 
    7984       14564 :     pfree(div);
    7985             : 
    7986             :     /*
    7987             :      * Finally, round the result to the requested precision.
    7988             :      */
    7989       14564 :     result->weight = res_weight;
    7990       14564 :     result->sign = res_sign;
    7991             : 
    7992             :     /* Round to target rscale (and set result->dscale) */
    7993       14564 :     if (round)
    7994       11824 :         round_var(result, rscale);
    7995             :     else
    7996        2740 :         trunc_var(result, rscale);
    7997             : 
    7998             :     /* Strip leading and trailing zeroes */
    7999       14564 :     strip_var(result);
    8000             : }
    8001             : 
    8002             : 
    8003             : /*
    8004             :  * Default scale selection for division
    8005             :  *
    8006             :  * Returns the appropriate result scale for the division result.
    8007             :  */
    8008             : static int
    8009       73284 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
    8010             : {
    8011             :     int         weight1,
    8012             :                 weight2,
    8013             :                 qweight,
    8014             :                 i;
    8015             :     NumericDigit firstdigit1,
    8016             :                 firstdigit2;
    8017             :     int         rscale;
    8018             : 
    8019             :     /*
    8020             :      * The result scale of a division isn't specified in any SQL standard. For
    8021             :      * PostgreSQL we select a result scale that will give at least
    8022             :      * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
    8023             :      * result no less accurate than float8; but use a scale not less than
    8024             :      * either input's display scale.
    8025             :      */
    8026             : 
    8027             :     /* Get the actual (normalized) weight and first digit of each input */
    8028             : 
    8029       73284 :     weight1 = 0;                /* values to use if var1 is zero */
    8030       73284 :     firstdigit1 = 0;
    8031       73284 :     for (i = 0; i < var1->ndigits; i++)
    8032             :     {
    8033       72186 :         firstdigit1 = var1->digits[i];
    8034       72186 :         if (firstdigit1 != 0)
    8035             :         {
    8036       72186 :             weight1 = var1->weight - i;
    8037       72186 :             break;
    8038             :         }
    8039             :     }
    8040             : 
    8041       73284 :     weight2 = 0;                /* values to use if var2 is zero */
    8042       73284 :     firstdigit2 = 0;
    8043       73284 :     for (i = 0; i < var2->ndigits; i++)
    8044             :     {
    8045       73256 :         firstdigit2 = var2->digits[i];
    8046       73256 :         if (firstdigit2 != 0)
    8047             :         {
    8048       73256 :             weight2 = var2->weight - i;
    8049       73256 :             break;
    8050             :         }
    8051             :     }
    8052             : 
    8053             :     /*
    8054             :      * Estimate weight of quotient.  If the two first digits are equal, we
    8055             :      * can't be sure, but assume that var1 is less than var2.
    8056             :      */
    8057       73284 :     qweight = weight1 - weight2;
    8058       73284 :     if (firstdigit1 <= firstdigit2)
    8059       65164 :         qweight--;
    8060             : 
    8061             :     /* Select result scale */
    8062       73284 :     rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
    8063       73284 :     rscale = Max(rscale, var1->dscale);
    8064       73284 :     rscale = Max(rscale, var2->dscale);
    8065       73284 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    8066       73284 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    8067             : 
    8068       73284 :     return rscale;
    8069             : }
    8070             : 
    8071             : 
    8072             : /*
    8073             :  * mod_var() -
    8074             :  *
    8075             :  *  Calculate the modulo of two numerics at variable level
    8076             :  */
    8077             : static void
    8078         452 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    8079             : {
    8080             :     NumericVar  tmp;
    8081             : 
    8082        2260 :     init_var(&tmp);
    8083             : 
    8084             :     /* ---------
    8085             :      * We do this using the equation
    8086             :      *      mod(x,y) = x - trunc(x/y)*y
    8087             :      * div_var can be persuaded to give us trunc(x/y) directly.
    8088             :      * ----------
    8089             :      */
    8090         452 :     div_var(var1, var2, &tmp, 0, false);
    8091             : 
    8092         448 :     mul_var(var2, &tmp, &tmp, var2->dscale);
    8093             : 
    8094         448 :     sub_var(var1, &tmp, result);
    8095             : 
    8096         448 :     free_var(&tmp);
    8097         448 : }
    8098             : 
    8099             : 
    8100             : /*
    8101             :  * div_mod_var() -
    8102             :  *
    8103             :  *  Calculate the truncated integer quotient and numeric remainder of two
    8104             :  *  numeric variables.  The remainder is precise to var2's dscale.
    8105             :  */
    8106             : static void
    8107        2740 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
    8108             :             NumericVar *quot, NumericVar *rem)
    8109             : {
    8110             :     NumericVar  q;
    8111             :     NumericVar  r;
    8112             : 
    8113       13700 :     init_var(&q);
    8114       13700 :     init_var(&r);
    8115             : 
    8116             :     /*
    8117             :      * Use div_var_fast() to get an initial estimate for the integer quotient.
    8118             :      * This might be inaccurate (per the warning in div_var_fast's comments),
    8119             :      * but we can correct it below.
    8120             :      */
    8121        2740 :     div_var_fast(var1, var2, &q, 0, false);
    8122             : 
    8123             :     /* Compute initial estimate of remainder using the quotient estimate. */
    8124        2740 :     mul_var(var2, &q, &r, var2->dscale);
    8125        2740 :     sub_var(var1, &r, &r);
    8126             : 
    8127             :     /*
    8128             :      * Adjust the results if necessary --- the remainder should have the same
    8129             :      * sign as var1, and its absolute value should be less than the absolute
    8130             :      * value of var2.
    8131             :      */
    8132        2740 :     while (r.ndigits != 0 && r.sign != var1->sign)
    8133             :     {
    8134             :         /* The absolute value of the quotient is too large */
    8135           0 :         if (var1->sign == var2->sign)
    8136             :         {
    8137           0 :             sub_var(&q, &const_one, &q);
    8138           0 :             add_var(&r, var2, &r);
    8139             :         }
    8140             :         else
    8141             :         {
    8142           0 :             add_var(&q, &const_one, &q);
    8143           0 :             sub_var(&r, var2, &r);
    8144             :         }
    8145             :     }
    8146             : 
    8147        2740 :     while (cmp_abs(&r, var2) >= 0)
    8148             :     {
    8149             :         /* The absolute value of the quotient is too small */
    8150           0 :         if (var1->sign == var2->sign)
    8151             :         {
    8152           0 :             add_var(&q, &const_one, &q);
    8153           0 :             sub_var(&r, var2, &r);
    8154             :         }
    8155             :         else
    8156             :         {
    8157           0 :             sub_var(&q, &const_one, &q);
    8158           0 :             add_var(&r, var2, &r);
    8159             :         }
    8160             :     }
    8161             : 
    8162        2740 :     set_var_from_var(&q, quot);
    8163        2740 :     set_var_from_var(&r, rem);
    8164             : 
    8165        2740 :     free_var(&q);
    8166        2740 :     free_var(&r);
    8167        2740 : }
    8168             : 
    8169             : 
    8170             : /*
    8171             :  * ceil_var() -
    8172             :  *
    8173             :  *  Return the smallest integer greater than or equal to the argument
    8174             :  *  on variable level
    8175             :  */
    8176             : static void
    8177         116 : ceil_var(const NumericVar *var, NumericVar *result)
    8178             : {
    8179             :     NumericVar  tmp;
    8180             : 
    8181         580 :     init_var(&tmp);
    8182         116 :     set_var_from_var(var, &tmp);
    8183             : 
    8184         116 :     trunc_var(&tmp, 0);
    8185             : 
    8186         116 :     if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
    8187          36 :         add_var(&tmp, &const_one, &tmp);
    8188             : 
    8189         116 :     set_var_from_var(&tmp, result);
    8190         116 :     free_var(&tmp);
    8191         116 : }
    8192             : 
    8193             : 
    8194             : /*
    8195             :  * floor_var() -
    8196             :  *
    8197             :  *  Return the largest integer equal to or less than the argument
    8198             :  *  on variable level
    8199             :  */
    8200             : static void
    8201         292 : floor_var(const NumericVar *var, NumericVar *result)
    8202             : {
    8203             :     NumericVar  tmp;
    8204             : 
    8205        1460 :     init_var(&tmp);
    8206         292 :     set_var_from_var(var, &tmp);
    8207             : 
    8208         292 :     trunc_var(&tmp, 0);
    8209             : 
    8210         292 :     if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
    8211          16 :         sub_var(&tmp, &const_one, &tmp);
    8212             : 
    8213         292 :     set_var_from_var(&tmp, result);
    8214         292 :     free_var(&tmp);
    8215         292 : }
    8216             : 
    8217             : 
    8218             : /*
    8219             :  * gcd_var() -
    8220             :  *
    8221             :  *  Calculate the greatest common divisor of two numerics at variable level
    8222             :  */
    8223             : static void
    8224         148 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    8225             : {
    8226             :     int         res_dscale;
    8227             :     int         cmp;
    8228             :     NumericVar  tmp_arg;
    8229             :     NumericVar  mod;
    8230             : 
    8231         148 :     res_dscale = Max(var1->dscale, var2->dscale);
    8232             : 
    8233             :     /*
    8234             :      * Arrange for var1 to be the number with the greater absolute value.
    8235             :      *
    8236             :      * This would happen automatically in the loop below, but avoids an
    8237             :      * expensive modulo operation.
    8238             :      */
    8239         148 :     cmp = cmp_abs(var1, var2);
    8240         148 :     if (cmp < 0)
    8241             :     {
    8242          56 :         const NumericVar *tmp = var1;
    8243             : 
    8244          56 :         var1 = var2;
    8245          56 :         var2 = tmp;
    8246             :     }
    8247             : 
    8248             :     /*
    8249             :      * Also avoid the taking the modulo if the inputs have the same absolute
    8250             :      * value, or if the smaller input is zero.
    8251             :      */
    8252         148 :     if (cmp == 0 || var2->ndigits == 0)
    8253             :     {
    8254          48 :         set_var_from_var(var1, result);
    8255          48 :         result->sign = NUMERIC_POS;
    8256          48 :         result->dscale = res_dscale;
    8257          48 :         return;
    8258             :     }
    8259             : 
    8260         500 :     init_var(&tmp_arg);
    8261         500 :     init_var(&mod);
    8262             : 
    8263             :     /* Use the Euclidean algorithm to find the GCD */
    8264         100 :     set_var_from_var(var1, &tmp_arg);
    8265         100 :     set_var_from_var(var2, result);
    8266             : 
    8267             :     for (;;)
    8268             :     {
    8269             :         /* this loop can take a while, so allow it to be interrupted */
    8270         392 :         CHECK_FOR_INTERRUPTS();
    8271             : 
    8272         392 :         mod_var(&tmp_arg, result, &mod);
    8273         392 :         if (mod.ndigits == 0)
    8274         100 :             break;
    8275         292 :         set_var_from_var(result, &tmp_arg);
    8276         292 :         set_var_from_var(&mod, result);
    8277             :     }
    8278         100 :     result->sign = NUMERIC_POS;
    8279         100 :     result->dscale = res_dscale;
    8280             : 
    8281         100 :     free_var(&tmp_arg);
    8282         100 :     free_var(&mod);
    8283             : }
    8284             : 
    8285             : 
    8286             : /*
    8287             :  * sqrt_var() -
    8288             :  *
    8289             :  *  Compute the square root of x using the Karatsuba Square Root algorithm.
    8290             :  *  NOTE: we allow rscale < 0 here, implying rounding before the decimal
    8291             :  *  point.
    8292             :  */
    8293             : static void
    8294        2464 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
    8295             : {
    8296             :     int         stat;
    8297             :     int         res_weight;
    8298             :     int         res_ndigits;
    8299             :     int         src_ndigits;
    8300             :     int         step;
    8301             :     int         ndigits[32];
    8302             :     int         blen;
    8303             :     int64       arg_int64;
    8304             :     int         src_idx;
    8305             :     int64       s_int64;
    8306             :     int64       r_int64;
    8307             :     NumericVar  s_var;
    8308             :     NumericVar  r_var;
    8309             :     NumericVar  a0_var;
    8310             :     NumericVar  a1_var;
    8311             :     NumericVar  q_var;
    8312             :     NumericVar  u_var;
    8313             : 
    8314        2464 :     stat = cmp_var(arg, &const_zero);
    8315        2464 :     if (stat == 0)
    8316             :     {
    8317           8 :         zero_var(result);
    8318           8 :         result->dscale = rscale;
    8319           8 :         return;
    8320             :     }
    8321             : 
    8322             :     /*
    8323             :      * SQL2003 defines sqrt() in terms of power, so we need to emit the right
    8324             :      * SQLSTATE error code if the operand is negative.
    8325             :      */
    8326        2456 :     if (stat < 0)
    8327           0 :         ereport(ERROR,
    8328             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    8329             :                  errmsg("cannot take square root of a negative number")));
    8330             : 
    8331       12280 :     init_var(&s_var);
    8332       12280 :     init_var(&r_var);
    8333       12280 :     init_var(&a0_var);
    8334       12280 :     init_var(&a1_var);
    8335       12280 :     init_var(&q_var);
    8336       12280 :     init_var(&u_var);
    8337             : 
    8338             :     /*
    8339             :      * The result weight is half the input weight, rounded towards minus
    8340             :      * infinity --- res_weight = floor(arg->weight / 2).
    8341             :      */
    8342        2456 :     if (arg->weight >= 0)
    8343        2248 :         res_weight = arg->weight / 2;
    8344             :     else
    8345         208 :         res_weight = -((-arg->weight - 1) / 2 + 1);
    8346             : 
    8347             :     /*
    8348             :      * Number of NBASE digits to compute.  To ensure correct rounding, compute
    8349             :      * at least 1 extra decimal digit.  We explicitly allow rscale to be
    8350             :      * negative here, but must always compute at least 1 NBASE digit.  Thus
    8351             :      * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
    8352             :      */
    8353        2456 :     if (rscale + 1 >= 0)
    8354        2456 :         res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
    8355             :     else
    8356           0 :         res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
    8357        2456 :     res_ndigits = Max(res_ndigits, 1);
    8358             : 
    8359             :     /*
    8360             :      * Number of source NBASE digits logically required to produce a result
    8361             :      * with this precision --- every digit before the decimal point, plus 2
    8362             :      * for each result digit after the decimal point (or minus 2 for each
    8363             :      * result digit we round before the decimal point).
    8364             :      */
    8365        2456 :     src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
    8366        2456 :     src_ndigits = Max(src_ndigits, 1);
    8367             : 
    8368             :     /* ----------
    8369             :      * From this point on, we treat the input and the result as integers and
    8370             :      * compute the integer square root and remainder using the Karatsuba
    8371             :      * Square Root algorithm, which may be written recursively as follows:
    8372             :      *
    8373             :      *  SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
    8374             :      *      [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
    8375             :      *        0 <= a0,a1,a2 < b and a3 >= b/4 ]
    8376             :      *      Let (s,r) = SqrtRem(a3*b + a2)
    8377             :      *      Let (q,u) = DivRem(r*b + a1, 2*s)
    8378             :      *      Let s = s*b + q
    8379             :      *      Let r = u*b + a0 - q^2
    8380             :      *      If r < 0 Then
    8381             :      *          Let r = r + s
    8382             :      *          Let s = s - 1
    8383             :      *          Let r = r + s
    8384             :      *      Return (s,r)
    8385             :      *
    8386             :      * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
    8387             :      * RR-3805, November 1999.  At the time of writing this was available
    8388             :      * on the net at <https://hal.inria.fr/inria-00072854>.
    8389             :      *
    8390             :      * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
    8391             :      * "choose a base b such that n requires at least four base-b digits to
    8392             :      * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
    8393             :      * than b".  For optimal performance, b should have approximately a
    8394             :      * quarter the number of digits in the input, so that the outer square
    8395             :      * root computes roughly twice as many digits as the inner one.  For
    8396             :      * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
    8397             :      *
    8398             :      * We implement the algorithm iteratively rather than recursively, to
    8399             :      * allow the working variables to be reused.  With this approach, each
    8400             :      * digit of the input is read precisely once --- src_idx tracks the number
    8401             :      * of input digits used so far.
    8402             :      *
    8403             :      * The array ndigits[] holds the number of NBASE digits of the input that
    8404             :      * will have been used at the end of each iteration, which roughly doubles
    8405             :      * each time.  Note that the array elements are stored in reverse order,
    8406             :      * so if the final iteration requires src_ndigits = 37 input digits, the
    8407             :      * array will contain [37,19,11,7,5,3], and we would start by computing
    8408             :      * the square root of the 3 most significant NBASE digits.
    8409             :      *
    8410             :      * In each iteration, we choose blen to be the largest integer for which
    8411             :      * the input number has a3 >= b/4, when written in the form above.  In
    8412             :      * general, this means blen = src_ndigits / 4 (truncated), but if
    8413             :      * src_ndigits is a multiple of 4, that might lead to the coefficient a3
    8414             :      * being less than b/4 (if the first input digit is less than NBASE/4), in
    8415             :      * which case we choose blen = src_ndigits / 4 - 1.  The number of digits
    8416             :      * in the inner square root is then src_ndigits - 2*blen.  So, for
    8417             :      * example, if we have src_ndigits = 26 initially, the array ndigits[]
    8418             :      * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
    8419             :      * the first input digit.
    8420             :      *
    8421             :      * Additionally, we can put an upper bound on the number of steps required
    8422             :      * as follows --- suppose that the number of source digits is an n-bit
    8423             :      * number in the range [2^(n-1), 2^n-1], then blen will be in the range
    8424             :      * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
    8425             :      * root will be in the range [2^(n-2), 2^(n-1)+1].  In the next step, blen
    8426             :      * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
    8427             :      * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
    8428             :      * This pattern repeats, and in the worst case the array ndigits[] will
    8429             :      * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
    8430             :      * will require n steps.  Therefore, since all digit array sizes are
    8431             :      * signed 32-bit integers, the number of steps required is guaranteed to
    8432             :      * be less than 32.
    8433             :      * ----------
    8434             :      */
    8435        2456 :     step = 0;
    8436       11748 :     while ((ndigits[step] = src_ndigits) > 4)
    8437             :     {
    8438             :         /* Choose b so that a3 >= b/4, as described above */
    8439        9292 :         blen = src_ndigits / 4;
    8440        9292 :         if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
    8441         216 :             blen--;
    8442             : 
    8443             :         /* Number of digits in the next step (inner square root) */
    8444        9292 :         src_ndigits -= 2 * blen;
    8445        9292 :         step++;
    8446             :     }
    8447             : 
    8448             :     /*
    8449             :      * First iteration (innermost square root and remainder):
    8450             :      *
    8451             :      * Here src_ndigits <= 4, and the input fits in an int64.  Its square root
    8452             :      * has at most 9 decimal digits, so estimate it using double precision
    8453             :      * arithmetic, which will in fact almost certainly return the correct
    8454             :      * result with no further correction required.
    8455             :      */
    8456        2456 :     arg_int64 = arg->digits[0];
    8457        7904 :     for (src_idx = 1; src_idx < src_ndigits; src_idx++)
    8458             :     {
    8459        5448 :         arg_int64 *= NBASE;
    8460        5448 :         if (src_idx < arg->ndigits)
    8461        4612 :             arg_int64 += arg->digits[src_idx];
    8462             :     }
    8463             : 
    8464        2456 :     s_int64 = (int64) sqrt((double) arg_int64);
    8465        2456 :     r_int64 = arg_int64 - s_int64 * s_int64;
    8466             : 
    8467             :     /*
    8468             :      * Use Newton's method to correct the result, if necessary.
    8469             :      *
    8470             :      * This uses integer division with truncation to compute the truncated
    8471             :      * integer square root by iterating using the formula x -> (x + n/x) / 2.
    8472             :      * This is known to converge to isqrt(n), unless n+1 is a perfect square.
    8473             :      * If n+1 is a perfect square, the sequence will oscillate between the two
    8474             :      * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
    8475             :      * checking the remainder.
    8476             :      */
    8477        2456 :     while (r_int64 < 0 || r_int64 > 2 * s_int64)
    8478             :     {
    8479           0 :         s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
    8480           0 :         r_int64 = arg_int64 - s_int64 * s_int64;
    8481             :     }
    8482             : 
    8483             :     /*
    8484             :      * Iterations with src_ndigits <= 8:
    8485             :      *
    8486             :      * The next 1 or 2 iterations compute larger (outer) square roots with
    8487             :      * src_ndigits <= 8, so the result still fits in an int64 (even though the
    8488             :      * input no longer does) and we can continue to compute using int64
    8489             :      * variables to avoid more expensive numeric computations.
    8490             :      *
    8491             :      * It is fairly easy to see that there is no risk of the intermediate
    8492             :      * values below overflowing 64-bit integers.  In the worst case, the
    8493             :      * previous iteration will have computed a 3-digit square root (of a
    8494             :      * 6-digit input less than NBASE^6 / 4), so at the start of this
    8495             :      * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
    8496             :      * less than 10^12.  In this case, blen will be 1, so numer will be less
    8497             :      * than 10^17, and denom will be less than 10^12 (and hence u will also be
    8498             :      * less than 10^12).  Finally, since q^2 = u*b + a0 - r, we can also be
    8499             :      * sure that q^2 < 10^17.  Therefore all these quantities fit comfortably
    8500             :      * in 64-bit integers.
    8501             :      */
    8502        2456 :     step--;
    8503        6096 :     while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
    8504             :     {
    8505             :         int         b;
    8506             :         int         a0;
    8507             :         int         a1;
    8508             :         int         i;
    8509             :         int64       numer;
    8510             :         int64       denom;
    8511             :         int64       q;
    8512             :         int64       u;
    8513             : 
    8514        3640 :         blen = (src_ndigits - src_idx) / 2;
    8515             : 
    8516             :         /* Extract a1 and a0, and compute b */
    8517        3640 :         a0 = 0;
    8518        3640 :         a1 = 0;
    8519        3640 :         b = 1;
    8520             : 
    8521        7376 :         for (i = 0; i < blen; i++, src_idx++)
    8522             :         {
    8523        3736 :             b *= NBASE;
    8524        3736 :             a1 *= NBASE;
    8525        3736 :             if (src_idx < arg->ndigits)
    8526        2760 :                 a1 += arg->digits[src_idx];
    8527             :         }
    8528             : 
    8529        7376 :         for (i = 0; i < blen; i++, src_idx++)
    8530             :         {
    8531        3736 :             a0 *= NBASE;
    8532        3736 :             if (src_idx < arg->ndigits)
    8533        2656 :                 a0 += arg->digits[src_idx];
    8534             :         }
    8535             : 
    8536             :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
    8537        3640 :         numer = r_int64 * b + a1;
    8538        3640 :         denom = 2 * s_int64;
    8539        3640 :         q = numer / denom;
    8540        3640 :         u = numer - q * denom;
    8541             : 
    8542             :         /* Compute s = s*b + q and r = u*b + a0 - q^2 */
    8543        3640 :         s_int64 = s_int64 * b + q;
    8544        3640 :         r_int64 = u * b + a0 - q * q;
    8545             : 
    8546        3640 :         if (r_int64 < 0)
    8547             :         {
    8548             :             /* s is too large by 1; set r += s, s--, r += s */
    8549         104 :             r_int64 += s_int64;
    8550         104 :             s_int64--;
    8551         104 :             r_int64 += s_int64;
    8552             :         }
    8553             : 
    8554             :         Assert(src_idx == src_ndigits); /* All input digits consumed */
    8555        3640 :         step--;
    8556             :     }
    8557             : 
    8558             :     /*
    8559             :      * On platforms with 128-bit integer support, we can further delay the
    8560             :      * need to use numeric variables.
    8561             :      */
    8562             : #ifdef HAVE_INT128
    8563        2456 :     if (step >= 0)
    8564             :     {
    8565             :         int128      s_int128;
    8566             :         int128      r_int128;
    8567             : 
    8568        2456 :         s_int128 = s_int64;
    8569        2456 :         r_int128 = r_int64;
    8570             : 
    8571             :         /*
    8572             :          * Iterations with src_ndigits <= 16:
    8573             :          *
    8574             :          * The result fits in an int128 (even though the input doesn't) so we
    8575             :          * use int128 variables to avoid more expensive numeric computations.
    8576             :          */
    8577        5368 :         while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
    8578             :         {
    8579             :             int64       b;
    8580             :             int64       a0;
    8581             :             int64       a1;
    8582             :             int64       i;
    8583             :             int128      numer;
    8584             :             int128      denom;
    8585             :             int128      q;
    8586             :             int128      u;
    8587             : 
    8588        2912 :             blen = (src_ndigits - src_idx) / 2;
    8589             : 
    8590             :             /* Extract a1 and a0, and compute b */
    8591        2912 :             a0 = 0;
    8592        2912 :             a1 = 0;
    8593        2912 :             b = 1;
    8594             : 
    8595        9684 :             for (i = 0; i < blen; i++, src_idx++)
    8596             :             {
    8597        6772 :                 b *= NBASE;
    8598        6772 :                 a1 *= NBASE;
    8599        6772 :                 if (src_idx < arg->ndigits)
    8600        3972 :                     a1 += arg->digits[src_idx];
    8601             :             }
    8602             : 
    8603        9684 :             for (i = 0; i < blen; i++, src_idx++)
    8604             :             {
    8605        6772 :                 a0 *= NBASE;
    8606        6772 :                 if (src_idx < arg->ndigits)
    8607        2980 :                     a0 += arg->digits[src_idx];
    8608             :             }
    8609             : 
    8610             :             /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
    8611        2912 :             numer = r_int128 * b + a1;
    8612        2912 :             denom = 2 * s_int128;
    8613        2912 :             q = numer / denom;
    8614        2912 :             u = numer - q * denom;
    8615             : 
    8616             :             /* Compute s = s*b + q and r = u*b + a0 - q^2 */
    8617        2912 :             s_int128 = s_int128 * b + q;
    8618        2912 :             r_int128 = u * b + a0 - q * q;
    8619             : 
    8620        2912 :             if (r_int128 < 0)
    8621             :             {
    8622             :                 /* s is too large by 1; set r += s, s--, r += s */
    8623         120 :                 r_int128 += s_int128;
    8624         120 :                 s_int128--;
    8625         120 :                 r_int128 += s_int128;
    8626             :             }
    8627             : 
    8628             :             Assert(src_idx == src_ndigits); /* All input digits consumed */
    8629        2912 :             step--;
    8630             :         }
    8631             : 
    8632             :         /*
    8633             :          * All remaining iterations require numeric variables.  Convert the
    8634             :          * integer values to NumericVar and continue.  Note that in the final
    8635             :          * iteration we don't need the remainder, so we can save a few cycles
    8636             :          * there by not fully computing it.
    8637             :          */
    8638        2456 :         int128_to_numericvar(s_int128, &s_var);
    8639        2456 :         if (step >= 0)
    8640        1544 :             int128_to_numericvar(r_int128, &r_var);
    8641             :     }
    8642             :     else
    8643             :     {
    8644           0 :         int64_to_numericvar(s_int64, &s_var);
    8645             :         /* step < 0, so we certainly don't need r */
    8646             :     }
    8647             : #else                           /* !HAVE_INT128 */
    8648             :     int64_to_numericvar(s_int64, &s_var);
    8649             :     if (step >= 0)
    8650             :         int64_to_numericvar(r_int64, &r_var);
    8651             : #endif                          /* HAVE_INT128 */
    8652             : 
    8653             :     /*
    8654             :      * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
    8655             :      * use numeric variables.
    8656             :      */
    8657        5196 :     while (step >= 0)
    8658             :     {
    8659             :         int         tmp_len;
    8660             : 
    8661        2740 :         src_ndigits = ndigits[step];
    8662        2740 :         blen = (src_ndigits - src_idx) / 2;
    8663             : 
    8664             :         /* Extract a1 and a0 */
    8665        2740 :         if (src_idx < arg->ndigits)
    8666             :         {
    8667        1008 :             tmp_len = Min(blen, arg->ndigits - src_idx);
    8668        1008 :             alloc_var(&a1_var, tmp_len);
    8669        1008 :             memcpy(a1_var.digits, arg->digits + src_idx,
    8670             :                    tmp_len * sizeof(NumericDigit));
    8671        1008 :             a1_var.weight = blen - 1;
    8672        1008 :             a1_var.sign = NUMERIC_POS;
    8673        1008 :             a1_var.dscale = 0;
    8674        1008 :             strip_var(&a1_var);
    8675             :         }
    8676             :         else
    8677             :         {
    8678        1732 :             zero_var(&a1_var);
    8679        1732 :             a1_var.dscale = 0;
    8680             :         }
    8681        2740 :         src_idx += blen;
    8682             : 
    8683        2740 :         if (src_idx < arg->ndigits)
    8684             :         {
    8685        1008 :             tmp_len = Min(blen, arg->ndigits - src_idx);
    8686        1008 :             alloc_var(&a0_var, tmp_len);
    8687        1008 :             memcpy(a0_var.digits, arg->digits + src_idx,
    8688             :                    tmp_len * sizeof(NumericDigit));
    8689        1008 :             a0_var.weight = blen - 1;
    8690        1008 :             a0_var.sign = NUMERIC_POS;
    8691        1008 :             a0_var.dscale = 0;
    8692        1008 :             strip_var(&a0_var);
    8693             :         }
    8694             :         else
    8695             :         {
    8696        1732 :             zero_var(&a0_var);
    8697        1732 :             a0_var.dscale = 0;
    8698             :         }
    8699        2740 :         src_idx += blen;
    8700             : 
    8701             :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
    8702        2740 :         set_var_from_var(&r_var, &q_var);
    8703        2740 :         q_var.weight += blen;
    8704        2740 :         add_var(&q_var, &a1_var, &q_var);
    8705        2740 :         add_var(&s_var, &s_var, &u_var);
    8706        2740 :         div_mod_var(&q_var, &u_var, &q_var, &u_var);
    8707             : 
    8708             :         /* Compute s = s*b + q */
    8709        2740 :         s_var.weight += blen;
    8710        2740 :         add_var(&s_var, &q_var, &s_var);
    8711             : 
    8712             :         /*
    8713             :          * Compute r = u*b + a0 - q^2.
    8714             :          *
    8715             :          * In the final iteration, we don't actually need r; we just need to
    8716             :          * know whether it is negative, so that we know whether to adjust s.
    8717             :          * So instead of the final subtraction we can just compare.
    8718             :          */
    8719        2740 :         u_var.weight += blen;
    8720        2740 :         add_var(&u_var, &a0_var, &u_var);
    8721        2740 :         mul_var(&q_var, &q_var, &q_var, 0);
    8722             : 
    8723        2740 :         if (step > 0)
    8724             :         {
    8725             :             /* Need r for later iterations */
    8726        1196 :             sub_var(&u_var, &q_var, &r_var);
    8727        1196 :             if (r_var.sign == NUMERIC_NEG)
    8728             :             {
    8729             :                 /* s is too large by 1; set r += s, s--, r += s */
    8730          80 :                 add_var(&r_var, &s_var, &r_var);
    8731          80 :                 sub_var(&s_var, &const_one, &s_var);
    8732          80 :                 add_var(&r_var, &s_var, &r_var);
    8733             :             }
    8734             :         }
    8735             :         else
    8736             :         {
    8737             :             /* Don't need r anymore, except to test if s is too large by 1 */
    8738        1544 :             if (cmp_var(&u_var, &q_var) < 0)
    8739          24 :                 sub_var(&s_var, &const_one, &s_var);
    8740             :         }
    8741             : 
    8742             :         Assert(src_idx == src_ndigits); /* All input digits consumed */
    8743        2740 :         step--;
    8744             :     }
    8745             : 
    8746             :     /*
    8747             :      * Construct the final result, rounding it to the requested precision.
    8748             :      */
    8749        2456 :     set_var_from_var(&s_var, result);
    8750        2456 :     result->weight = res_weight;
    8751        2456 :     result->sign = NUMERIC_POS;
    8752             : 
    8753             :     /* Round to target rscale (and set result->dscale) */
    8754        2456 :     round_var(result, rscale);
    8755             : 
    8756             :     /* Strip leading and trailing zeroes */
    8757        2456 :     strip_var(result);
    8758             : 
    8759        2456 :     free_var(&s_var);
    8760        2456 :     free_var(&r_var);
    8761        2456 :     free_var(&a0_var);
    8762        2456 :     free_var(&a1_var);
    8763        2456 :     free_var(&q_var);
    8764        2456 :     free_var(&u_var);
    8765             : }
    8766             : 
    8767             : 
    8768             : /*
    8769             :  * exp_var() -
    8770             :  *
    8771             :  *  Raise e to the power of x, computed to rscale fractional digits
    8772             :  */
    8773             : static void
    8774          80 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
    8775             : {
    8776             :     NumericVar  x;
    8777             :     NumericVar  elem;
    8778             :     NumericVar  ni;
    8779             :     double      val;
    8780             :     int         dweight;
    8781             :     int         ndiv2;
    8782             :     int         sig_digits;
    8783             :     int         local_rscale;
    8784             : 
    8785         400 :     init_var(&x);
    8786         400 :     init_var(&elem);
    8787         400 :     init_var(&ni);
    8788             : 
    8789          80 :     set_var_from_var(arg, &x);
    8790             : 
    8791             :     /*
    8792             :      * Estimate the dweight of the result using floating point arithmetic, so
    8793             :      * that we can choose an appropriate local rscale for the calculation.
    8794             :      */
    8795          80 :     val = numericvar_to_double_no_overflow(&x);
    8796             : 
    8797             :     /* Guard against overflow */
    8798             :     /* If you change this limit, see also power_var()'s limit */
    8799          80 :     if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
    8800           0 :         ereport(ERROR,
    8801             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    8802             :                  errmsg("value overflows numeric format")));
    8803             : 
    8804             :     /* decimal weight = log10(e^x) = x * log10(e) */
    8805          80 :     dweight = (int) (val * 0.434294481903252);
    8806             : 
    8807             :     /*
    8808             :      * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
    8809             :      * 2^n, to improve the convergence rate of the Taylor series.
    8810             :      */
    8811          80 :     if (Abs(val) > 0.01)
    8812             :     {
    8813             :         NumericVar  tmp;
    8814             : 
    8815         380 :         init_var(&tmp);
    8816          76 :         set_var_from_var(&const_two, &tmp);
    8817             : 
    8818          76 :         ndiv2 = 1;
    8819          76 :         val /= 2;
    8820             : 
    8821         916 :         while (Abs(val) > 0.01)
    8822             :         {
    8823         840 :             ndiv2++;
    8824         840 :             val /= 2;
    8825         840 :             add_var(&tmp, &tmp, &tmp);
    8826             :         }
    8827             : 
    8828          76 :         local_rscale = x.dscale + ndiv2;
    8829          76 :         div_var_fast(&x, &tmp, &x, local_rscale, true);
    8830             : 
    8831          76 :         free_var(&tmp);
    8832             :     }
    8833             :     else
    8834           4 :         ndiv2 = 0;
    8835             : 
    8836             :     /*
    8837             :      * Set the scale for the Taylor series expansion.  The final result has
    8838             :      * (dweight + rscale + 1) significant digits.  In addition, we have to
    8839             :      * raise the Taylor series result to the power 2^ndiv2, which introduces
    8840             :      * an error of up to around log10(2^ndiv2) digits, so work with this many
    8841             :      * extra digits of precision (plus a few more for good measure).
    8842             :      */
    8843          80 :     sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
    8844          80 :     sig_digits = Max(sig_digits, 0) + 8;
    8845             : 
    8846          80 :     local_rscale = sig_digits - 1;
    8847             : 
    8848             :     /*
    8849             :      * Use the Taylor series
    8850             :      *
    8851             :      * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
    8852             :      *
    8853             :      * Given the limited range of x, this should converge reasonably quickly.
    8854             :      * We run the series until the terms fall below the local_rscale limit.
    8855             :      */
    8856          80 :     add_var(&const_one, &x, result);
    8857             : 
    8858          80 :     mul_var(&x, &x, &elem, local_rscale);
    8859          80 :     set_var_from_var(&const_two, &ni);
    8860          80 :     div_var_fast(&elem, &ni, &elem, local_rscale, true);
    8861             : 
    8862        3128 :     while (elem.ndigits != 0)
    8863             :     {
    8864        3048 :         add_var(result, &elem, result);
    8865             : 
    8866        3048 :         mul_var(&elem, &x, &elem, local_rscale);
    8867        3048 :         add_var(&ni, &const_one, &ni);
    8868        3048 :         div_var_fast(&elem, &ni, &elem, local_rscale, true);
    8869             :     }
    8870             : 
    8871             :     /*
    8872             :      * Compensate for the argument range reduction.  Since the weight of the
    8873             :      * result doubles with each multiplication, we can reduce the local rscale
    8874             :      * as we proceed.
    8875             :      */
    8876         996 :     while (ndiv2-- > 0)
    8877             :     {
    8878         916 :         local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
    8879         916 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    8880         916 :         mul_var(result, result, result, local_rscale);
    8881             :     }
    8882             : 
    8883             :     /* Round to requested rscale */
    8884          80 :     round_var(result, rscale);
    8885             : 
    8886          80 :     free_var(&x);
    8887          80 :     free_var(&elem);
    8888          80 :     free_var(&ni);
    8889          80 : }
    8890             : 
    8891             : 
    8892             : /*
    8893             :  * Estimate the dweight of the most significant decimal digit of the natural
    8894             :  * logarithm of a number.
    8895             :  *
    8896             :  * Essentially, we're approximating log10(abs(ln(var))).  This is used to
    8897             :  * determine the appropriate rscale when computing natural logarithms.
    8898             :  */
    8899             : static int
    8900         360 : estimate_ln_dweight(const NumericVar *var)
    8901             : {
    8902             :     int         ln_dweight;
    8903             : 
    8904         656 :     if (cmp_var(var, &const_zero_point_nine) >= 0 &&
    8905         296 :         cmp_var(var, &const_one_point_one) <= 0)
    8906          20 :     {
    8907             :         /*
    8908             :          * 0.9 <= var <= 1.1
    8909             :          *
    8910             :          * ln(var) has a negative weight (possibly very large).  To get a
    8911             :          * reasonably accurate result, estimate it using ln(1+x) ~= x.
    8912             :          */
    8913             :         NumericVar  x;
    8914             : 
    8915         100 :         init_var(&x);
    8916          20 :         sub_var(var, &const_one, &x);
    8917             : 
    8918          20 :         if (x.ndigits > 0)
    8919             :         {
    8920             :             /* Use weight of most significant decimal digit of x */
    8921          16 :             ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
    8922             :         }
    8923             :         else
    8924             :         {
    8925             :             /* x = 0.  Since ln(1) = 0 exactly, we don't need extra digits */
    8926           4 :             ln_dweight = 0;
    8927             :         }
    8928             : 
    8929          20 :         free_var(&x);
    8930             :     }
    8931             :     else
    8932             :     {
    8933             :         /*
    8934             :          * Estimate the logarithm using the first couple of digits from the
    8935             :          * input number.  This will give an accurate result whenever the input
    8936             :          * is not too close to 1.
    8937             :          */
    8938         340 :         if (var->ndigits > 0)
    8939             :         {
    8940             :             int         digits;
    8941             :             int         dweight;
    8942             :             double      ln_var;
    8943             : 
    8944         324 :             digits = var->digits[0];
    8945         324 :             dweight = var->weight * DEC_DIGITS;
    8946             : 
    8947         324 :             if (var->ndigits > 1)
    8948             :             {
    8949         220 :                 digits = digits * NBASE + var->digits[1];
    8950         220 :                 dweight -= DEC_DIGITS;
    8951             :             }
    8952             : 
    8953             :             /*----------
    8954             :              * We have var ~= digits * 10^dweight
    8955             :              * so ln(var) ~= ln(digits) + dweight * ln(10)
    8956             :              *----------
    8957             :              */
    8958         324 :             ln_var = log((double) digits) + dweight * 2.302585092994046;
    8959         324 :             ln_dweight = (int) log10(Abs(ln_var));
    8960             :         }
    8961             :         else
    8962             :         {
    8963             :             /* Caller should fail on ln(0), but for the moment return zero */
    8964          16 :             ln_dweight = 0;
    8965             :         }
    8966             :     }
    8967             : 
    8968         360 :     return ln_dweight;
    8969             : }
    8970             : 
    8971             : 
    8972             : /*
    8973             :  * ln_var() -
    8974             :  *
    8975             :  *  Compute the natural log of x
    8976             :  */
    8977             : static void
    8978         396 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
    8979             : {
    8980             :     NumericVar  x;
    8981             :     NumericVar  xx;
    8982             :     NumericVar  ni;
    8983             :     NumericVar  elem;
    8984             :     NumericVar  fact;
    8985             :     int         nsqrt;
    8986             :     int         local_rscale;
    8987             :     int         cmp;
    8988             : 
    8989         396 :     cmp = cmp_var(arg, &const_zero);
    8990         396 :     if (cmp == 0)
    8991          16 :         ereport(ERROR,
    8992             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    8993             :                  errmsg("cannot take logarithm of zero")));
    8994         380 :     else if (cmp < 0)
    8995          20 :         ereport(ERROR,
    8996             :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    8997             :                  errmsg("cannot take logarithm of a negative number")));
    8998             : 
    8999        1800 :     init_var(&x);
    9000        1800 :     init_var(&xx);
    9001        1800 :     init_var(&ni);
    9002        1800 :     init_var(&elem);
    9003        1800 :     init_var(&fact);
    9004             : 
    9005         360 :     set_var_from_var(arg, &x);
    9006         360 :     set_var_from_var(&const_two, &fact);
    9007             : 
    9008             :     /*
    9009             :      * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
    9010             :      *
    9011             :      * The final logarithm will have up to around rscale+6 significant digits.
    9012             :      * Each sqrt() will roughly halve the weight of x, so adjust the local
    9013             :      * rscale as we work so that we keep this many significant digits at each
    9014             :      * step (plus a few more for good measure).
    9015             :      *
    9016             :      * Note that we allow local_rscale < 0 during this input reduction
    9017             :      * process, which implies rounding before the decimal point.  sqrt_var()
    9018             :      * explicitly supports this, and it significantly reduces the work
    9019             :      * required to reduce very large inputs to the required range.  Once the
    9020             :      * input reduction is complete, x.weight will be 0 and its display scale
    9021             :      * will be non-negative again.
    9022             :      */
    9023         360 :     nsqrt = 0;
    9024         568 :     while (cmp_var(&x, &const_zero_point_nine) <= 0)
    9025             :     {
    9026         208 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
    9027         208 :         sqrt_var(&x, &x, local_rscale);
    9028         208 :         mul_var(&fact, &const_two, &fact, 0);
    9029         208 :         nsqrt++;
    9030             :     }
    9031        2292 :     while (cmp_var(&x, &const_one_point_one) >= 0)
    9032             :     {
    9033        1932 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
    9034        1932 :         sqrt_var(&x, &x, local_rscale);
    9035        1932 :         mul_var(&fact, &const_two, &fact, 0);
    9036        1932 :         nsqrt++;
    9037             :     }
    9038             : 
    9039             :     /*
    9040             :      * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
    9041             :      *
    9042             :      * z + z^3/3 + z^5/5 + ...
    9043             :      *
    9044             :      * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
    9045             :      * due to the above range-reduction of x.
    9046             :      *
    9047             :      * The convergence of this is not as fast as one would like, but is
    9048             :      * tolerable given that z is small.
    9049             :      *
    9050             :      * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
    9051             :      * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
    9052             :      * digits of precision (plus a few more for good measure).
    9053             :      */
    9054         360 :     local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
    9055             : 
    9056         360 :     sub_var(&x, &const_one, result);
    9057         360 :     add_var(&x, &const_one, &elem);
    9058         360 :     div_var_fast(result, &elem, result, local_rscale, true);
    9059         360 :     set_var_from_var(result, &xx);
    9060         360 :     mul_var(result, result, &x, local_rscale);
    9061             : 
    9062         360 :     set_var_from_var(&const_one, &ni);
    9063             : 
    9064             :     for (;;)
    9065             :     {
    9066        8404 :         add_var(&ni, &const_two, &ni);
    9067        8404 :         mul_var(&xx, &x, &xx, local_rscale);
    9068        8404 :         div_var_fast(&xx, &ni, &elem, local_rscale, true);
    9069             : 
    9070        8404 :         if (elem.ndigits == 0)
    9071         360 :             break;
    9072             : 
    9073        8044 :         add_var(result, &elem, result);
    9074             : 
    9075        8044 :         if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
    9076           0 :             break;
    9077             :     }
    9078             : 
    9079             :     /* Compensate for argument range reduction, round to requested rscale */
    9080         360 :     mul_var(result, &fact, result, rscale);
    9081             : 
    9082         360 :     free_var(&x);
    9083         360 :     free_var(&xx);
    9084         360 :     free_var(&ni);
    9085         360 :     free_var(&elem);
    9086         360 :     free_var(&fact);
    9087         360 : }
    9088             : 
    9089             : 
    9090             : /*
    9091             :  * log_var() -
    9092             :  *
    9093             :  *  Compute the logarithm of num in a given base.
    9094             :  *
    9095             :  *  Note: this routine chooses dscale of the result.
    9096             :  */
    9097             : static void
    9098         104 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
    9099             : {
    9100             :     NumericVar  ln_base;
    9101             :     NumericVar  ln_num;
    9102             :     int         ln_base_dweight;
    9103             :     int         ln_num_dweight;
    9104             :     int         result_dweight;
    9105             :     int         rscale;
    9106             :     int         ln_base_rscale;
    9107             :     int         ln_num_rscale;
    9108             : 
    9109         520 :     init_var(&ln_base);
    9110         520 :     init_var(&ln_num);
    9111             : 
    9112             :     /* Estimated dweights of ln(base), ln(num) and the final result */
    9113         104 :     ln_base_dweight = estimate_ln_dweight(base);
    9114         104 :     ln_num_dweight = estimate_ln_dweight(num);
    9115         104 :     result_dweight = ln_num_dweight - ln_base_dweight;
    9116             : 
    9117             :     /*
    9118             :      * Select the scale of the result so that it will have at least
    9119             :      * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
    9120             :      * input's display scale.
    9121             :      */
    9122         104 :     rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
    9123         104 :     rscale = Max(rscale, base->dscale);
    9124         104 :     rscale = Max(rscale, num->dscale);
    9125         104 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9126         104 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    9127             : 
    9128             :     /*
    9129             :      * Set the scales for ln(base) and ln(num) so that they each have more
    9130             :      * significant digits than the final result.
    9131             :      */
    9132         104 :     ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
    9133         104 :     ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9134             : 
    9135         104 :     ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
    9136         104 :     ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9137             : 
    9138             :     /* Form natural logarithms */
    9139         104 :     ln_var(base, &ln_base, ln_base_rscale);
    9140          92 :     ln_var(num, &ln_num, ln_num_rscale);
    9141             : 
    9142             :     /* Divide and round to the required scale */
    9143          76 :     div_var_fast(&ln_num, &ln_base, result, rscale, true);
    9144             : 
    9145          72 :     free_var(&ln_num);
    9146          72 :     free_var(&ln_base);
    9147          72 : }
    9148             : 
    9149             : 
    9150             : /*
    9151             :  * power_var() -
    9152             :  *
    9153             :  *  Raise base to the power of exp
    9154             :  *
    9155             :  *  Note: this routine chooses dscale of the result.
    9156             :  */
    9157             : static void
    9158         144 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
    9159             : {
    9160             :     NumericVar  ln_base;
    9161             :     NumericVar  ln_num;
    9162             :     int         ln_dweight;
    9163             :     int         rscale;
    9164             :     int         local_rscale;
    9165             :     double      val;
    9166             : 
    9167             :     /* If exp can be represented as an integer, use power_var_int */
    9168         144 :     if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
    9169             :     {
    9170             :         /* exact integer, but does it fit in int? */
    9171             :         int64       expval64;
    9172             : 
    9173          88 :         if (numericvar_to_int64(exp, &expval64))
    9174             :         {
    9175          88 :             int         expval = (int) expval64;
    9176             : 
    9177             :             /* Test for overflow by reverse-conversion. */
    9178          88 :             if ((int64) expval == expval64)
    9179             :             {
    9180             :                 /* Okay, select rscale */
    9181          88 :                 rscale = NUMERIC_MIN_SIG_DIGITS;
    9182          88 :                 rscale = Max(rscale, base->dscale);
    9183          88 :                 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9184          88 :                 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    9185             : 
    9186          88 :                 power_var_int(base, expval, result, rscale);
    9187          80 :                 return;
    9188             :             }
    9189             :         }
    9190             :     }
    9191             : 
    9192             :     /*
    9193             :      * This avoids log(0) for cases of 0 raised to a non-integer.  0 ^ 0 is
    9194             :      * handled by power_var_int().
    9195             :      */
    9196          56 :     if (cmp_var(base, &const_zero) == 0)
    9197             :     {
    9198           8 :         set_var_from_var(&const_zero, result);
    9199           8 :         result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
    9200           8 :         return;
    9201             :     }
    9202             : 
    9203         240 :     init_var(&ln_base);
    9204         240 :     init_var(&ln_num);
    9205             : 
    9206             :     /*----------
    9207             :      * Decide on the scale for the ln() calculation.  For this we need an
    9208             :      * estimate of the weight of the result, which we obtain by doing an
    9209             :      * initial low-precision calculation of exp * ln(base).
    9210             :      *
    9211             :      * We want result = e ^ (exp * ln(base))
    9212             :      * so result dweight = log10(result) = exp * ln(base) * log10(e)
    9213             :      *
    9214             :      * We also perform a crude overflow test here so that we can exit early if
    9215             :      * the full-precision result is sure to overflow, and to guard against
    9216             :      * integer overflow when determining the scale for the real calculation.
    9217             :      * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
    9218             :      * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
    9219             :      * Since the values here are only approximations, we apply a small fuzz
    9220             :      * factor to this overflow test and let exp_var() determine the exact
    9221             :      * overflow threshold so that it is consistent for all inputs.
    9222             :      *----------
    9223             :      */
    9224          48 :     ln_dweight = estimate_ln_dweight(base);
    9225             : 
    9226          48 :     local_rscale = 8 - ln_dweight;
    9227          48 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9228          48 :     local_rscale = Min(local_rscale, NUMERIC_MAX_DISPLAY_SCALE);
    9229             : 
    9230          48 :     ln_var(base, &ln_base, local_rscale);
    9231             : 
    9232          48 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
    9233             : 
    9234          48 :     val = numericvar_to_double_no_overflow(&ln_num);
    9235             : 
    9236             :     /* initial overflow test with fuzz factor */
    9237          48 :     if (Abs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
    9238           0 :         ereport(ERROR,
    9239             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    9240             :                  errmsg("value overflows numeric format")));
    9241             : 
    9242          48 :     val *= 0.434294481903252;   /* approximate decimal result weight */
    9243             : 
    9244             :     /* choose the result scale */
    9245          48 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
    9246          48 :     rscale = Max(rscale, base->dscale);
    9247          48 :     rscale = Max(rscale, exp->dscale);
    9248          48 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9249          48 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    9250             : 
    9251             :     /* set the scale for the real exp * ln(base) calculation */
    9252          48 :     local_rscale = rscale + (int) val - ln_dweight + 8;
    9253          48 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9254             : 
    9255             :     /* and do the real calculation */
    9256             : 
    9257          48 :     ln_var(base, &ln_base, local_rscale);
    9258             : 
    9259          48 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
    9260             : 
    9261          48 :     exp_var(&ln_num, result, rscale);
    9262             : 
    9263          48 :     free_var(&ln_num);
    9264          48 :     free_var(&ln_base);
    9265             : }
    9266             : 
    9267             : /*
    9268             :  * power_var_int() -
    9269             :  *
    9270             :  *  Raise base to the power of exp, where exp is an integer.
    9271             :  */
    9272             : static void
    9273         128 : power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
    9274             : {
    9275             :     double      f;
    9276             :     int         p;
    9277             :     int         i;
    9278             :     int         sig_digits;
    9279             :     unsigned int mask;
    9280             :     bool        neg;
    9281             :     NumericVar  base_prod;
    9282             :     int         local_rscale;
    9283             : 
    9284             :     /* Handle some common special cases, as well as corner cases */
    9285         128 :     switch (exp)
    9286             :     {
    9287          28 :         case 0:
    9288             : 
    9289             :             /*
    9290             :              * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
    9291             :              * it as 1 because most programming languages do this. SQL:2003
    9292             :              * also requires a return value of 1.
    9293             :              * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
    9294             :              */
    9295          28 :             set_var_from_var(&const_one, result);
    9296          28 :             result->dscale = rscale; /* no need to round */
    9297          36 :             return;
    9298           0 :         case 1:
    9299           0 :             set_var_from_var(base, result);
    9300           0 :             round_var(result, rscale);
    9301           0 :             return;
    9302           0 :         case -1:
    9303           0 :             div_var(&const_one, base, result, rscale, true);
    9304           0 :             return;
    9305           0 :         case 2:
    9306           0 :             mul_var(base, base, result, rscale);
    9307           0 :             return;
    9308         100 :         default:
    9309         100 :             break;
    9310             :     }
    9311             : 
    9312             :     /* Handle the special case where the base is zero */
    9313         100 :     if (base->ndigits == 0)
    9314             :     {
    9315           0 :         if (exp < 0)
    9316           0 :             ereport(ERROR,
    9317             :                     (errcode(ERRCODE_DIVISION_BY_ZERO),
    9318             :                      errmsg("division by zero")));
    9319           0 :         zero_var(result);
    9320           0 :         result->dscale = rscale;
    9321           0 :         return;
    9322             :     }
    9323             : 
    9324             :     /*
    9325             :      * The general case repeatedly multiplies base according to the bit
    9326             :      * pattern of exp.
    9327             :      *
    9328             :      * First we need to estimate the weight of the result so that we know how
    9329             :      * many significant digits are needed.
    9330             :      */
    9331         100 :     f = base->digits[0];
    9332         100 :     p = base->weight * DEC_DIGITS;
    9333             : 
    9334         124 :     for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
    9335             :     {
    9336          24 :         f = f * NBASE + base->digits[i];
    9337          24 :         p -= DEC_DIGITS;
    9338             :     }
    9339             : 
    9340             :     /*----------
    9341             :      * We have base ~= f * 10^p
    9342             :      * so log10(result) = log10(base^exp) ~= exp * (log10(f) + p)
    9343             :      *----------
    9344             :      */
    9345         100 :     f = exp * (log10(f) + p);
    9346             : 
    9347             :     /*
    9348             :      * Apply crude overflow/underflow tests so we can exit early if the result
    9349             :      * certainly will overflow/underflow.
    9350             :      */
    9351         100 :     if (f > 3 * SHRT_MAX * DEC_DIGITS)
    9352           8 :         ereport(ERROR,
    9353             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    9354             :                  errmsg("value overflows numeric format")));
    9355          92 :     if (f + 1 < -rscale || f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
    9356             :     {
    9357           8 :         zero_var(result);
    9358           8 :         result->dscale = rscale;
    9359           8 :         return;
    9360             :     }
    9361             : 
    9362             :     /*
    9363             :      * Approximate number of significant digits in the result.  Note that the
    9364             :      * underflow test above means that this is necessarily >= 0.
    9365             :      */
    9366          84 :     sig_digits = 1 + rscale + (int) f;
    9367             : 
    9368             :     /*
    9369             :      * The multiplications to produce the result may introduce an error of up
    9370             :      * to around log10(abs(exp)) digits, so work with this many extra digits
    9371             :      * of precision (plus a few more for good measure).
    9372             :      */
    9373          84 :     sig_digits += (int) log(Abs(exp)) + 8;
    9374             : 
    9375             :     /*
    9376             :      * Now we can proceed with the multiplications.
    9377             :      */
    9378          84 :     neg = (exp < 0);
    9379          84 :     mask = Abs(exp);
    9380             : 
    9381         420 :     init_var(&base_prod);
    9382          84 :     set_var_from_var(base, &base_prod);
    9383             : 
    9384          84 :     if (mask & 1)
    9385          48 :         set_var_from_var(base, result);
    9386             :     else
    9387          36 :         set_var_from_var(&const_one, result);
    9388             : 
    9389         732 :     while ((mask >>= 1) > 0)
    9390             :     {
    9391             :         /*
    9392             :          * Do the multiplications using rscales large enough to hold the
    9393             :          * results to the required number of significant digits, but don't
    9394             :          * waste time by exceeding the scales of the numbers themselves.
    9395             :          */
    9396         648 :         local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
    9397         648 :         local_rscale = Min(local_rscale, 2 * base_prod.dscale);
    9398         648 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9399             : 
    9400         648 :         mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
    9401             : 
    9402         648 :         if (mask & 1)
    9403             :         {
    9404         532 :             local_rscale = sig_digits -
    9405         532 :                 (base_prod.weight + result->weight) * DEC_DIGITS;
    9406         532 :             local_rscale = Min(local_rscale,
    9407             :                                base_prod.dscale + result->dscale);
    9408         532 :             local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9409             : 
    9410         532 :             mul_var(&base_prod, result, result, local_rscale);
    9411             :         }
    9412             : 
    9413             :         /*
    9414             :          * When abs(base) > 1, the number of digits to the left of the decimal
    9415             :          * point in base_prod doubles at each iteration, so if exp is large we
    9416             :          * could easily spend large amounts of time and memory space doing the
    9417             :          * multiplications.  But once the weight exceeds what will fit in
    9418             :          * int16, the final result is guaranteed to overflow (or underflow, if
    9419             :          * exp < 0), so we can give up before wasting too many cycles.
    9420             :          */
    9421         648 :         if (base_prod.weight > SHRT_MAX || result->weight > SHRT_MAX)
    9422             :         {
    9423             :             /* overflow, unless neg, in which case result should be 0 */
    9424           0 :             if (!neg)
    9425           0 :                 ereport(ERROR,
    9426             :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    9427             :                          errmsg("value overflows numeric format")));
    9428           0 :             zero_var(result);
    9429           0 :             neg = false;
    9430           0 :             break;
    9431             :         }
    9432             :     }
    9433             : 
    9434          84 :     free_var(&base_prod);
    9435             : 
    9436             :     /* Compensate for input sign, and round to requested rscale */
    9437          84 :     if (neg)
    9438          12 :         div_var_fast(&const_one, result, result, rscale, true);
    9439             :     else
    9440          72 :         round_var(result, rscale);
    9441             : }
    9442             : 
    9443             : 
    9444             : /* ----------------------------------------------------------------------
    9445             :  *
    9446             :  * Following are the lowest level functions that operate unsigned
    9447             :  * on the variable level
    9448             :  *
    9449             :  * ----------------------------------------------------------------------
    9450             :  */
    9451             : 
    9452             : 
    9453             : /* ----------
    9454             :  * cmp_abs() -
    9455             :  *
    9456             :  *  Compare the absolute values of var1 and var2
    9457             :  *  Returns:    -1 for ABS(var1) < ABS(var2)
    9458             :  *              0  for ABS(var1) == ABS(var2)
    9459             :  *              1  for ABS(var1) > ABS(var2)
    9460             :  * ----------
    9461             :  */
    9462             : static int
    9463      155126 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
    9464             : {
    9465      465378 :     return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
    9466      155126 :                           var2->digits, var2->ndigits, var2->weight);
    9467             : }
    9468             : 
    9469             : /* ----------
    9470             :  * cmp_abs_common() -
    9471             :  *
    9472             :  *  Main routine of cmp_abs(). This function can be used by both
    9473             :  *  NumericVar and Numeric.
    9474             :  * ----------
    9475             :  */
    9476             : static int
    9477     3568846 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
    9478             :                const NumericDigit *var2digits, int var2ndigits, int var2weight)
    9479             : {
    9480     3568846 :     int         i1 = 0;
    9481     3568846 :     int         i2 = 0;
    9482             : 
    9483             :     /* Check any digits before the first common digit */
    9484             : 
    9485     3568846 :     while (var1weight > var2weight && i1 < var1ndigits)
    9486             :     {
    9487       15274 :         if (var1digits[i1++] != 0)
    9488       15274 :             return 1;
    9489           0 :         var1weight--;
    9490             :     }
    9491     3553572 :     while (var2weight > var1weight && i2 < var2ndigits)
    9492             :     {
    9493       16848 :         if (var2digits[i2++] != 0)
    9494       16848 :             return -1;
    9495           0 :         var2weight--;
    9496             :     }
    9497             : 
    9498             :     /* At this point, either w1 == w2 or we've run out of digits */
    9499             : 
    9500     3536724 :     if (var1weight == var2weight)
    9501             :     {
    9502     6435960 :         while (i1 < var1ndigits && i2 < var2ndigits)
    9503             :         {
    9504     4023394 :             int         stat = var1digits[i1++] - var2digits[i2++];
    9505             : 
    9506     4023394 :             if (stat)
    9507             :             {
    9508     1124154 :                 if (stat > 0)
    9509      696570 :                     return 1;
    9510      427584 :                 return -1;
    9511             :             }
    9512             :         }
    9513             :     }
    9514             : 
    9515             :     /*
    9516             :      * At this point, we've run out of digits on one side or the other; so any
    9517             :      * remaining nonzero digits imply that side is larger
    9518             :      */
    9519     2412830 :     while (i1 < var1ndigits)
    9520             :     {
    9521        1034 :         if (var1digits[i1++] != 0)
    9522         774 :             return 1;
    9523             :     }
    9524     2411976 :     while (i2 < var2ndigits)
    9525             :     {
    9526         396 :         if (var2digits[i2++] != 0)
    9527         216 :             return -1;
    9528             :     }
    9529             : 
    9530     2411580 :     return 0;
    9531             : }
    9532             : 
    9533             : 
    9534             : /*
    9535             :  * add_abs() -
    9536             :  *
    9537             :  *  Add the absolute values of two variables into result.
    9538             :  *  result might point to one of the operands without danger.
    9539             :  */
    9540             : static void
    9541       42740 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    9542             : {
    9543             :     NumericDigit *res_buf;
    9544             :     NumericDigit *res_digits;
    9545             :     int         res_ndigits;
    9546             :     int         res_weight;
    9547             :     int         res_rscale,
    9548             :                 rscale1,
    9549             :                 rscale2;
    9550             :     int         res_dscale;
    9551             :     int         i,
    9552             :                 i1,
    9553             :                 i2;
    9554       42740 :     int         carry = 0;
    9555             : 
    9556             :     /* copy these values into local vars for speed in inner loop */
    9557       42740 :     int         var1ndigits = var1->ndigits;
    9558       42740 :     int         var2ndigits = var2->ndigits;
    9559       42740 :     NumericDigit *var1digits = var1->digits;
    9560       42740 :     NumericDigit *var2digits = var2->digits;
    9561             : 
    9562       42740 :     res_weight = Max(var1->weight, var2->weight) + 1;
    9563             : 
    9564       42740 :     res_dscale = Max(var1->dscale, var2->dscale);
    9565             : 
    9566             :     /* Note: here we are figuring rscale in base-NBASE digits */
    9567       42740 :     rscale1 = var1->ndigits - var1->weight - 1;
    9568       42740 :     rscale2 = var2->ndigits - var2->weight - 1;
    9569       42740 :     res_rscale = Max(rscale1, rscale2);
    9570             : 
    9571       42740 :     res_ndigits = res_rscale + res_weight + 1;
    9572       42740 :     if (res_ndigits <= 0)
    9573           0 :         res_ndigits = 1;
    9574             : 
    9575       42740 :     res_buf = digitbuf_alloc(res_ndigits + 1);
    9576       42740 :     res_buf[0] = 0;             /* spare digit for later rounding */
    9577       42740 :     res_digits = res_buf + 1;
    9578             : 
    9579       42740 :     i1 = res_rscale + var1->weight + 1;
    9580       42740 :     i2 = res_rscale + var2->weight + 1;
    9581      991602 :     for (i = res_ndigits - 1; i >= 0; i--)
    9582             :     {
    9583      948862 :         i1--;
    9584      948862 :         i2--;
    9585      948862 :         if (i1 >= 0 && i1 < var1ndigits)
    9586      684818 :             carry += var1digits[i1];
    9587      948862 :         if (i2 >= 0 && i2 < var2ndigits)
    9588      508838 :             carry += var2digits[i2];
    9589             : 
    9590      948862 :         if (carry >= NBASE)
    9591             :         {
    9592      147292 :             res_digits[i] = carry - NBASE;
    9593      147292 :             carry = 1;
    9594             :         }
    9595             :         else
    9596             :         {
    9597      801570 :             res_digits[i] = carry;
    9598      801570 :             carry = 0;
    9599             :         }
    9600             :     }
    9601             : 
    9602             :     Assert(carry == 0);         /* else we failed to allow for carry out */
    9603             : 
    9604       42740 :     digitbuf_free(result->buf);
    9605       42740 :     result->ndigits = res_ndigits;
    9606       42740 :     result->buf = res_buf;
    9607       42740 :     result->digits = res_digits;
    9608       42740 :     result->weight = res_weight;
    9609       42740 :     result->dscale = res_dscale;
    9610             : 
    9611             :     /* Remove leading/trailing zeroes */
    9612       42740 :     strip_var(result);
    9613       42740 : }
    9614             : 
    9615             : 
    9616             : /*
    9617             :  * sub_abs()
    9618             :  *
    9619             :  *  Subtract the absolute value of var2 from the absolute value of var1
    9620             :  *  and store in result. result might point to one of the operands
    9621             :  *  without danger.
    9622             :  *
    9623             :  *  ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
    9624             :  */
    9625             : static void
    9626      129724 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    9627             : {
    9628             :     NumericDigit *res_buf;
    9629             :     NumericDigit *res_digits;
    9630             :     int         res_ndigits;
    9631             :     int         res_weight;
    9632             :     int         res_rscale,
    9633             :                 rscale1,
    9634             :                 rscale2;
    9635             :     int         res_dscale;
    9636             :     int         i,
    9637             :                 i1,
    9638             :                 i2;
    9639      129724 :     int         borrow = 0;
    9640             : 
    9641             :     /* copy these values into local vars for speed in inner loop */
    9642      129724 :     int         var1ndigits = var1->ndigits;
    9643      129724 :     int         var2ndigits = var2->ndigits;
    9644      129724 :     NumericDigit *var1digits = var1->digits;
    9645      129724 :     NumericDigit *var2digits = var2->digits;
    9646             : 
    9647      129724 :     res_weight = var1->weight;
    9648             : 
    9649      129724 :     res_dscale = Max(var1->dscale, var2->dscale);
    9650             : 
    9651             :     /* Note: here we are figuring rscale in base-NBASE digits */
    9652      129724 :     rscale1 = var1->ndigits - var1->weight - 1;
    9653      129724 :     rscale2 = var2->ndigits - var2->weight - 1;
    9654      129724 :     res_rscale = Max(rscale1, rscale2);
    9655             : 
    9656      129724 :     res_ndigits = res_rscale + res_weight + 1;
    9657      129724 :     if (res_ndigits <= 0)
    9658           0 :         res_ndigits = 1;
    9659             : 
    9660      129724 :     res_buf = digitbuf_alloc(res_ndigits + 1);
    9661      129724 :     res_buf[0] = 0;             /* spare digit for later rounding */
    9662      129724 :     res_digits = res_buf + 1;
    9663             : 
    9664      129724 :     i1 = res_rscale + var1->weight + 1;
    9665      129724 :     i2 = res_rscale + var2->weight + 1;
    9666      849108 :     for (i = res_ndigits - 1; i >= 0; i--)
    9667             :     {
    9668      719384 :         i1--;
    9669      719384 :         i2--;
    9670      719384 :         if (i1 >= 0 && i1 < var1ndigits)
    9671      563854 :             borrow += var1digits[i1];
    9672      719384 :         if (i2 >= 0 && i2 < var2ndigits)
    9673      563466 :             borrow -= var2digits[i2];
    9674             : 
    9675      719384 :         if (borrow < 0)
    9676             :         {
    9677      184940 :             res_digits[i] = borrow + NBASE;
    9678      184940 :             borrow = -1;
    9679             :         }
    9680             :         else
    9681             :         {
    9682      534444 :             res_digits[i] = borrow;
    9683      534444 :             borrow = 0;
    9684             :         }
    9685             :     }
    9686             : 
    9687             :     Assert(borrow == 0);        /* else caller gave us var1 < var2 */
    9688             : 
    9689      129724 :     digitbuf_free(result->buf);
    9690      129724 :     result->ndigits = res_ndigits;
    9691      129724 :     result->buf = res_buf;
    9692      129724 :     result->digits = res_digits;
    9693      129724 :     result->weight = res_weight;
    9694      129724 :     result->dscale = res_dscale;
    9695             : 
    9696             :     /* Remove leading/trailing zeroes */
    9697      129724 :     strip_var(result);
    9698      129724 : }
    9699             : 
    9700             : /*
    9701             :  * round_var
    9702             :  *
    9703             :  * Round the value of a variable to no more than rscale decimal digits
    9704             :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
    9705             :  * rounding before the decimal point.
    9706             :  */
    9707             : static void
    9708      445450 : round_var(NumericVar *var, int rscale)
    9709             : {
    9710      445450 :     NumericDigit *digits = var->digits;
    9711             :     int         di;
    9712             :     int         ndigits;
    9713             :     int         carry;
    9714             : 
    9715      445450 :     var->dscale = rscale;
    9716             : 
    9717             :     /* decimal digits wanted */
    9718      445450 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
    9719             : 
    9720             :     /*
    9721             :      * If di = 0, the value loses all digits, but could round up to 1 if its
    9722             :      * first extra digit is >= 5.  If di < 0 the result must be 0.
    9723             :      */
    9724      445450 :     if (di < 0)
    9725             :     {
    9726          40 :         var->ndigits = 0;
    9727          40 :         var->weight = 0;
    9728          40 :         var->sign = NUMERIC_POS;
    9729             :     }
    9730             :     else
    9731             :     {
    9732             :         /* NBASE digits wanted */
    9733      445410 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
    9734             : 
    9735             :         /* 0, or number of decimal digits to keep in last NBASE digit */
    9736      445410 :         di %= DEC_DIGITS;
    9737             : 
    9738      445410 :         if (ndigits < var->ndigits ||
    9739      343122 :             (ndigits == var->ndigits && di > 0))
    9740             :         {
    9741      426500 :             var->ndigits = ndigits;
    9742             : 
    9743             : #if DEC_DIGITS == 1
    9744             :             /* di must be zero */
    9745             :             carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
    9746             : #else
    9747      426500 :             if (di == 0)
    9748       80562 :                 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
    9749             :             else
    9750             :             {
    9751             :                 /* Must round within last NBASE digit */
    9752             :                 int         extra,
    9753             :                             pow10;
    9754             : 
    9755             : #if DEC_DIGITS == 4
    9756      345938 :                 pow10 = round_powers[di];
    9757             : #elif DEC_DIGITS == 2
    9758             :                 pow10 = 10;
    9759             : #else
    9760             : #error unsupported NBASE
    9761             : #endif
    9762      345938 :                 extra = digits[--ndigits] % pow10;
    9763      345938 :                 digits[ndigits] -= extra;
    9764      345938 :                 carry = 0;
    9765      345938 :                 if (extra >= pow10 / 2)
    9766             :                 {
    9767       11402 :                     pow10 += digits[ndigits];
    9768       11402 :                     if (pow10 >= NBASE)
    9769             :                     {
    9770         442 :                         pow10 -= NBASE;
    9771         442 :                         carry = 1;
    9772             :                     }
    9773       11402 :                     digits[ndigits] = pow10;
    9774             :                 }
    9775             :             }
    9776             : #endif
    9777             : 
    9778             :             /* Propagate carry if needed */
    9779      432332 :             while (carry)
    9780             :             {
    9781        5832 :                 carry += digits[--ndigits];
    9782        5832 :                 if (carry >= NBASE)
    9783             :                 {
    9784         142 :                     digits[ndigits] = carry - NBASE;
    9785         142 :                     carry = 1;
    9786             :                 }
    9787             :                 else
    9788             :                 {
    9789        5690 :                     digits[ndigits] = carry;
    9790        5690 :                     carry = 0;
    9791             :                 }
    9792             :             }
    9793             : 
    9794      426500 :             if (ndigits < 0)
    9795             :             {
    9796             :                 Assert(ndigits == -1);  /* better not have added > 1 digit */
    9797             :                 Assert(var->digits > var->buf);
    9798          52 :                 var->digits--;
    9799          52 :                 var->ndigits++;
    9800          52 :                 var->weight++;
    9801             :             }
    9802             :         }
    9803             :     }
    9804      445450 : }
    9805             : 
    9806             : /*
    9807             :  * trunc_var
    9808             :  *
    9809             :  * Truncate (towards zero) the value of a variable at rscale decimal digits
    9810             :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
    9811             :  * truncation before the decimal point.
    9812             :  */
    9813             : static void
    9814        4272 : trunc_var(NumericVar *var, int rscale)
    9815             : {
    9816             :     int         di;
    9817             :     int         ndigits;
    9818             : 
    9819        4272 :     var->dscale = rscale;
    9820             : 
    9821             :     /* decimal digits wanted */
    9822        4272 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
    9823             : 
    9824             :     /*
    9825             :      * If di <= 0, the value loses all digits.
    9826             :      */
    9827        4272 :     if (di <= 0)
    9828             :     {
    9829          40 :         var->ndigits = 0;
    9830          40 :         var->weight = 0;
    9831          40 :         var->sign = NUMERIC_POS;
    9832             :     }
    9833             :     else
    9834             :     {
    9835             :         /* NBASE digits wanted */
    9836        4232 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
    9837             : 
    9838        4232 :         if (ndigits <= var->ndigits)
    9839             :         {
    9840        4108 :             var->ndigits = ndigits;
    9841             : 
    9842             : #if DEC_DIGITS == 1
    9843             :             /* no within-digit stuff to worry about */
    9844             : #else
    9845             :             /* 0, or number of decimal digits to keep in last NBASE digit */
    9846        4108 :             di %= DEC_DIGITS;
    9847             : 
    9848        4108 :             if (di > 0)
    9849             :             {
    9850             :                 /* Must truncate within last NBASE digit */
    9851           0 :                 NumericDigit *digits = var->digits;
    9852             :                 int         extra,
    9853             :                             pow10;
    9854             : 
    9855             : #if DEC_DIGITS == 4
    9856           0 :                 pow10 = round_powers[di];
    9857             : #elif DEC_DIGITS == 2
    9858             :                 pow10 = 10;
    9859             : #else
    9860             : #error unsupported NBASE
    9861             : #endif
    9862           0 :                 extra = digits[--ndigits] % pow10;
    9863           0 :                 digits[ndigits] -= extra;
    9864             :             }
    9865             : #endif
    9866             :         }
    9867             :     }
    9868        4272 : }
    9869             : 
    9870             : /*
    9871             :  * strip_var
    9872             :  *
    9873             :  * Strip any leading and trailing zeroes from a numeric variable
    9874             :  */
    9875             : static void
    9876      771978 : strip_var(NumericVar *var)
    9877             : {
    9878      771978 :     NumericDigit *digits = var->digits;
    9879      771978 :     int         ndigits = var->ndigits;
    9880             : 
    9881             :     /* Strip leading zeroes */
    9882     1543770 :     while (ndigits > 0 && *digits == 0)
    9883             :     {
    9884      771792 :         digits++;
    9885      771792 :         var->weight--;
    9886      771792 :         ndigits--;
    9887             :     }
    9888             : 
    9889             :     /* Strip trailing zeroes */
    9890     1104338 :     while (ndigits > 0 && digits[ndigits - 1] == 0)
    9891      332360 :         ndigits--;
    9892             : 
    9893             :     /* If it's zero, normalize the sign and weight */
    9894      771978 :     if (ndigits == 0)
    9895             :     {
    9896        3104 :         var->sign = NUMERIC_POS;
    9897        3104 :         var->weight = 0;
    9898             :     }
    9899             : 
    9900      771978 :     var->digits = digits;
    9901      771978 :     var->ndigits = ndigits;
    9902      771978 : }
    9903             : 
    9904             : 
    9905             : /* ----------------------------------------------------------------------
    9906             :  *
    9907             :  * Fast sum accumulator functions
    9908             :  *
    9909             :  * ----------------------------------------------------------------------
    9910             :  */
    9911             : 
    9912             : /*
    9913             :  * Reset the accumulator's value to zero.  The buffers to hold the digits
    9914             :  * are not free'd.
    9915             :  */
    9916             : static void
    9917          12 : accum_sum_reset(NumericSumAccum *accum)
    9918             : {
    9919             :     int         i;
    9920             : 
    9921          12 :     accum->dscale = 0;
    9922          44 :     for (i = 0; i < accum->ndigits; i++)
    9923             :     {
    9924          32 :         accum->pos_digits[i] = 0;
    9925          32 :         accum->neg_digits[i] = 0;
    9926             :     }
    9927          12 : }
    9928             : 
    9929             : /*
    9930             :  * Accumulate a new value.
    9931             :  */
    9932             : static void
    9933     1090252 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
    9934             : {
    9935             :     int32      *accum_digits;
    9936             :     int         i,
    9937             :                 val_i;
    9938             :     int         val_ndigits;
    9939             :     NumericDigit *val_digits;
    9940             : 
    9941             :     /*
    9942             :      * If we have accumulated too many values since the last carry
    9943             :      * propagation, do it now, to avoid overflowing.  (We could allow more
    9944             :      * than NBASE - 1, if we reserved two extra digits, rather than one, for
    9945             :      * carry propagation.  But even with NBASE - 1, this needs to be done so
    9946             :      * seldom, that the performance difference is negligible.)
    9947             :      */
    9948     1090252 :     if (accum->num_uncarried == NBASE - 1)
    9949          80 :         accum_sum_carry(accum);
    9950             : 
    9951             :     /*
    9952             :      * Adjust the weight or scale of the old value, so that it can accommodate
    9953             :      * the new value.
    9954             :      */
    9955     1090252 :     accum_sum_rescale(accum, val);
    9956             : 
    9957             :     /* */
    9958     1090252 :     if (val->sign == NUMERIC_POS)
    9959      689816 :         accum_digits = accum->pos_digits;
    9960             :     else
    9961      400436 :         accum_digits = accum->neg_digits;
    9962             : 
    9963             :     /* copy these values into local vars for speed in loop */
    9964     1090252 :     val_ndigits = val->ndigits;
    9965     1090252 :     val_digits = val->digits;
    9966             : 
    9967     1090252 :     i = accum->weight - val->weight;
    9968     2261656 :     for (val_i = 0; val_i < val_ndigits; val_i++)
    9969             :     {
    9970     1171404 :         accum_digits[i] += (int32) val_digits[val_i];
    9971     1171404 :         i++;
    9972             :     }
    9973             : 
    9974     1090252 :     accum->num_uncarried++;
    9975     1090252 : }
    9976             : 
    9977             : /*
    9978             :  * Propagate carries.
    9979             :  */
    9980             : static void
    9981      115192 : accum_sum_carry(NumericSumAccum *accum)
    9982             : {
    9983             :     int         i;
    9984             :     int         ndigits;
    9985             :     int32      *dig;
    9986             :     int32       carry;
    9987      115192 :     int32       newdig = 0;
    9988             : 
    9989             :     /*
    9990             :      * If no new values have been added since last carry propagation, nothing
    9991             :      * to do.
    9992             :      */
    9993      115192 :     if (accum->num_uncarried == 0)
    9994          48 :         return;
    9995             : 
    9996             :     /*
    9997             :      * We maintain that the weight of the accumulator is always one larger
    9998             :      * than needed to hold the current value, before carrying, to make sure
    9999             :      * there is enough space for the possible extra digit when carry is
   10000             :      * propagated.  We cannot expand the buffer here, unless we require
   10001             :      * callers of accum_sum_final() to switch to the right memory context.
   10002             :      */
   10003             :     Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
   10004             : 
   10005      115144 :     ndigits = accum->ndigits;
   10006             : 
   10007             :     /* Propagate carry in the positive sum */
   10008      115144 :     dig = accum->pos_digits;
   10009      115144 :     carry = 0;
   10010      426312 :     for (i = ndigits - 1; i >= 0; i--)
   10011             :     {
   10012      311168 :         newdig = dig[i] + carry;
   10013      311168 :         if (newdig >= NBASE)
   10014             :         {
   10015       41960 :             carry = newdig / NBASE;
   10016       41960 :             newdig -= carry * NBASE;
   10017             :         }
   10018             :         else
   10019      269208 :             carry = 0;
   10020      311168 :         dig[i] = newdig;
   10021             :     }
   10022             :     /* Did we use up the digit reserved for carry propagation? */
   10023      115144 :     if (newdig > 0)
   10024        1696 :         accum->have_carry_space = false;
   10025             : 
   10026             :     /* And the same for the negative sum */
   10027      115144 :     dig = accum->neg_digits;
   10028      115144 :     carry = 0;
   10029      426312 :     for (i = ndigits - 1; i >= 0; i--)
   10030             :     {
   10031      311168 :         newdig = dig[i] + carry;
   10032      311168 :         if (newdig >= NBASE)
   10033             :         {
   10034         164 :             carry = newdig / NBASE;
   10035         164 :             newdig -= carry * NBASE;
   10036             :         }
   10037             :         else
   10038      311004 :             carry = 0;
   10039      311168 :         dig[i] = newdig;
   10040             :     }
   10041      115144 :     if (newdig > 0)
   10042          20 :         accum->have_carry_space = false;
   10043             : 
   10044      115144 :     accum->num_uncarried = 0;
   10045             : }
   10046             : 
   10047             : /*
   10048             :  * Re-scale accumulator to accommodate new value.
   10049             :  *
   10050             :  * If the new value has more digits than the current digit buffers in the
   10051             :  * accumulator, enlarge the buffers.
   10052             :  */
   10053             : static void
   10054     1090252 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
   10055             : {
   10056     1090252 :     int         old_weight = accum->weight;
   10057     1090252 :     int         old_ndigits = accum->ndigits;
   10058             :     int         accum_ndigits;
   10059             :     int         accum_weight;
   10060             :     int         accum_rscale;
   10061             :     int         val_rscale;
   10062             : 
   10063     1090252 :     accum_weight = old_weight;
   10064     1090252 :     accum_ndigits = old_ndigits;
   10065             : 
   10066             :     /*
   10067             :      * Does the new value have a larger weight? If so, enlarge the buffers,
   10068             :      * and shift the existing value to the new weight, by adding leading
   10069             :      * zeros.
   10070             :      *
   10071             :      * We enforce that the accumulator always has a weight one larger than
   10072             :      * needed for the inputs, so that we have space for an extra digit at the
   10073             :      * final carry-propagation phase, if necessary.
   10074             :      */
   10075     1090252 :     if (val->weight >= accum_weight)
   10076             :     {
   10077      174696 :         accum_weight = val->weight + 1;
   10078      174696 :         accum_ndigits = accum_ndigits + (accum_weight - old_weight);
   10079             :     }
   10080             : 
   10081             :     /*
   10082             :      * Even though the new value is small, we might've used up the space
   10083             :      * reserved for the carry digit in the last call to accum_sum_carry().  If
   10084             :      * so, enlarge to make room for another one.
   10085             :      */
   10086      915556 :     else if (!accum->have_carry_space)
   10087             :     {
   10088          16 :         accum_weight++;
   10089          16 :         accum_ndigits++;
   10090             :     }
   10091             : 
   10092             :     /* Is the new value wider on the right side? */
   10093     1090252 :     accum_rscale = accum_ndigits - accum_weight - 1;
   10094     1090252 :     val_rscale = val->ndigits - val->weight - 1;
   10095     1090252 :     if (val_rscale > accum_rscale)
   10096      114692 :         accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
   10097             : 
   10098     1090252 :     if (accum_ndigits != old_ndigits ||
   10099             :         accum_weight != old_weight)
   10100             :     {
   10101             :         int32      *new_pos_digits;
   10102             :         int32      *new_neg_digits;
   10103             :         int         weightdiff;
   10104             : 
   10105      174864 :         weightdiff = accum_weight - old_weight;
   10106             : 
   10107      174864 :         new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
   10108      174864 :         new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
   10109             : 
   10110      174864 :         if (accum->pos_digits)
   10111             :         {
   10112       60204 :             memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
   10113             :                    old_ndigits * sizeof(int32));
   10114       60204 :             pfree(accum->pos_digits);
   10115             : 
   10116       60204 :             memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
   10117             :                    old_ndigits * sizeof(int32));
   10118       60204 :             pfree(accum->neg_digits);
   10119             :         }
   10120             : 
   10121      174864 :         accum->pos_digits = new_pos_digits;
   10122      174864 :         accum->neg_digits = new_neg_digits;
   10123             : 
   10124      174864 :         accum->weight = accum_weight;
   10125      174864 :         accum->ndigits = accum_ndigits;
   10126             : 
   10127             :         Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
   10128      174864 :         accum->have_carry_space = true;
   10129             :     }
   10130             : 
   10131     1090252 :     if (val->dscale > accum->dscale)
   10132         160 :         accum->dscale = val->dscale;
   10133     1090252 : }
   10134             : 
   10135             : /*
   10136             :  * Return the current value of the accumulator.  This perform final carry
   10137             :  * propagation, and adds together the positive and negative sums.
   10138             :  *
   10139             :  * Unlike all the other routines, the caller is not required to switch to
   10140             :  * the memory context that holds the accumulator.
   10141             :  */
   10142             : static void
   10143      115112 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
   10144             : {
   10145             :     int         i;
   10146             :     NumericVar  pos_var;
   10147             :     NumericVar  neg_var;
   10148             : 
   10149      115112 :     if (accum->ndigits == 0)
   10150             :     {
   10151           0 :         set_var_from_var(&const_zero, result);
   10152           0 :         return;
   10153             :     }
   10154             : 
   10155             :     /* Perform final carry */
   10156      115112 :     accum_sum_carry(accum);
   10157             : 
   10158             :     /* Create NumericVars representing the positive and negative sums */
   10159      575560 :     init_var(&pos_var);
   10160      575560 :     init_var(&neg_var);
   10161             : 
   10162      115112 :     pos_var.ndigits = neg_var.ndigits = accum->ndigits;
   10163      115112 :     pos_var.weight = neg_var.weight = accum->weight;
   10164      115112 :     pos_var.dscale = neg_var.dscale = accum->dscale;
   10165      115112 :     pos_var.sign = NUMERIC_POS;
   10166      115112 :     neg_var.sign = NUMERIC_NEG;
   10167             : 
   10168      115112 :     pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
   10169      115112 :     neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
   10170             : 
   10171      426104 :     for (i = 0; i < accum->ndigits; i++)
   10172             :     {
   10173             :         Assert(accum->pos_digits[i] < NBASE);
   10174      310992 :         pos_var.digits[i] = (int16) accum->pos_digits[i];
   10175             : 
   10176             :         Assert(accum->neg_digits[i] < NBASE);
   10177      310992 :         neg_var.digits[i] = (int16) accum->neg_digits[i];
   10178             :     }
   10179             : 
   10180             :     /* And add them together */
   10181      115112 :     add_var(&pos_var, &neg_var, result);
   10182             : 
   10183             :     /* Remove leading/trailing zeroes */
   10184      115112 :     strip_var(result);
   10185             : }
   10186             : 
   10187             : /*
   10188             :  * Copy an accumulator's state.
   10189             :  *
   10190             :  * 'dst' is assumed to be uninitialized beforehand.  No attempt is made at
   10191             :  * freeing old values.
   10192             :  */
   10193             : static void
   10194           0 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
   10195             : {
   10196           0 :     dst->pos_digits = palloc(src->ndigits * sizeof(int32));
   10197           0 :     dst->neg_digits = palloc(src->ndigits * sizeof(int32));
   10198             : 
   10199           0 :     memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
   10200           0 :     memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
   10201           0 :     dst->num_uncarried = src->num_uncarried;
   10202           0 :     dst->ndigits = src->ndigits;
   10203           0 :     dst->weight = src->weight;
   10204           0 :     dst->dscale = src->dscale;
   10205           0 : }
   10206             : 
   10207             : /*
   10208             :  * Add the current value of 'accum2' into 'accum'.
   10209             :  */
   10210             : static void
   10211           0 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
   10212             : {
   10213             :     NumericVar  tmp_var;
   10214             : 
   10215           0 :     init_var(&tmp_var);
   10216             : 
   10217           0 :     accum_sum_final(accum2, &tmp_var);
   10218           0 :     accum_sum_add(accum, &tmp_var);
   10219             : 
   10220           0 :     free_var(&tmp_var);
   10221           0 : }

Generated by: LCOV version 1.13