LCOV - code coverage report
Current view: top level - src/backend/utils/adt - numeric.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 94.8 % 3977 3771
Test Date: 2026-03-10 02:15:01 Functions: 99.1 % 211 209
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-2026, 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 "common/hashfn.h"
      30              : #include "common/int.h"
      31              : #include "common/int128.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 "optimizer/optimizer.h"
      39              : #include "utils/array.h"
      40              : #include "utils/builtins.h"
      41              : #include "utils/float.h"
      42              : #include "utils/guc.h"
      43              : #include "utils/numeric.h"
      44              : #include "utils/pg_lsn.h"
      45              : #include "utils/sortsupport.h"
      46              : 
      47              : /* ----------
      48              :  * Uncomment the following to enable compilation of dump_numeric()
      49              :  * and dump_var() and to get a dump of any result produced by make_result().
      50              :  * ----------
      51              :  */
      52              : /* #define NUMERIC_DEBUG */
      53              : 
      54              : 
      55              : /* ----------
      56              :  * Local data types
      57              :  *
      58              :  * Numeric values are represented in a base-NBASE floating point format.
      59              :  * Each "digit" ranges from 0 to NBASE-1.  The type NumericDigit is signed
      60              :  * and wide enough to store a digit.  We assume that NBASE*NBASE can fit in
      61              :  * an int.  Although the purely calculational routines could handle any even
      62              :  * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
      63              :  * in NBASE a power of ten, so that I/O conversions and decimal rounding
      64              :  * are easy.  Also, it's actually more efficient if NBASE is rather less than
      65              :  * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
      66              :  * postpone processing carries.
      67              :  *
      68              :  * Values of NBASE other than 10000 are considered of historical interest only
      69              :  * and are no longer supported in any sense; no mechanism exists for the client
      70              :  * to discover the base, so every client supporting binary mode expects the
      71              :  * base-10000 format.  If you plan to change this, also note the numeric
      72              :  * abbreviation code, which assumes NBASE=10000.
      73              :  * ----------
      74              :  */
      75              : 
      76              : #if 0
      77              : #define NBASE       10
      78              : #define HALF_NBASE  5
      79              : #define DEC_DIGITS  1           /* decimal digits per NBASE digit */
      80              : #define MUL_GUARD_DIGITS    4   /* these are measured in NBASE digits */
      81              : #define DIV_GUARD_DIGITS    8
      82              : 
      83              : typedef signed char NumericDigit;
      84              : #endif
      85              : 
      86              : #if 0
      87              : #define NBASE       100
      88              : #define HALF_NBASE  50
      89              : #define DEC_DIGITS  2           /* decimal digits per NBASE digit */
      90              : #define MUL_GUARD_DIGITS    3   /* these are measured in NBASE digits */
      91              : #define DIV_GUARD_DIGITS    6
      92              : 
      93              : typedef signed char NumericDigit;
      94              : #endif
      95              : 
      96              : #if 1
      97              : #define NBASE       10000
      98              : #define HALF_NBASE  5000
      99              : #define DEC_DIGITS  4           /* decimal digits per NBASE digit */
     100              : #define MUL_GUARD_DIGITS    2   /* these are measured in NBASE digits */
     101              : #define DIV_GUARD_DIGITS    4
     102              : 
     103              : typedef int16 NumericDigit;
     104              : #endif
     105              : 
     106              : #define NBASE_SQR   (NBASE * NBASE)
     107              : 
     108              : /*
     109              :  * The Numeric type as stored on disk.
     110              :  *
     111              :  * If the high bits of the first word of a NumericChoice (n_header, or
     112              :  * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
     113              :  * numeric follows the NumericShort format; if they are NUMERIC_POS or
     114              :  * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
     115              :  * the value is a NaN or Infinity.  We currently always store SPECIAL values
     116              :  * using just two bytes (i.e. only n_header), but previous releases used only
     117              :  * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
     118              :  * on disk if a database has been migrated using pg_upgrade.  In either case,
     119              :  * the low-order bits of a special value's header are reserved and currently
     120              :  * should always be set to zero.
     121              :  *
     122              :  * In the NumericShort format, the remaining 14 bits of the header word
     123              :  * (n_short.n_header) are allocated as follows: 1 for sign (positive or
     124              :  * negative), 6 for dynamic scale, and 7 for weight.  In practice, most
     125              :  * commonly-encountered values can be represented this way.
     126              :  *
     127              :  * In the NumericLong format, the remaining 14 bits of the header word
     128              :  * (n_long.n_sign_dscale) represent the display scale; and the weight is
     129              :  * stored separately in n_weight.
     130              :  *
     131              :  * NOTE: by convention, values in the packed form have been stripped of
     132              :  * all leading and trailing zero digits (where a "digit" is of base NBASE).
     133              :  * In particular, if the value is zero, there will be no digits at all!
     134              :  * The weight is arbitrary in that case, but we normally set it to zero.
     135              :  */
     136              : 
     137              : struct NumericShort
     138              : {
     139              :     uint16      n_header;       /* Sign + display scale + weight */
     140              :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
     141              : };
     142              : 
     143              : struct NumericLong
     144              : {
     145              :     uint16      n_sign_dscale;  /* Sign + display scale */
     146              :     int16       n_weight;       /* Weight of 1st digit  */
     147              :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
     148              : };
     149              : 
     150              : union NumericChoice
     151              : {
     152              :     uint16      n_header;       /* Header word */
     153              :     struct NumericLong n_long;  /* Long form (4-byte header) */
     154              :     struct NumericShort n_short;    /* Short form (2-byte header) */
     155              : };
     156              : 
     157              : struct NumericData
     158              : {
     159              :     int32       vl_len_;        /* varlena header (do not touch directly!) */
     160              :     union NumericChoice choice; /* choice of format */
     161              : };
     162              : 
     163              : 
     164              : /*
     165              :  * Interpretation of high bits.
     166              :  */
     167              : 
     168              : #define NUMERIC_SIGN_MASK   0xC000
     169              : #define NUMERIC_POS         0x0000
     170              : #define NUMERIC_NEG         0x4000
     171              : #define NUMERIC_SHORT       0x8000
     172              : #define NUMERIC_SPECIAL     0xC000
     173              : 
     174              : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
     175              : #define NUMERIC_IS_SHORT(n)     (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
     176              : #define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
     177              : 
     178              : #define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
     179              : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
     180              : 
     181              : /*
     182              :  * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
     183              :  * header; otherwise, we want the long one.  Instead of testing against each
     184              :  * value, we can just look at the high bit, for a slight efficiency gain.
     185              :  */
     186              : #define NUMERIC_HEADER_IS_SHORT(n)  (((n)->choice.n_header & 0x8000) != 0)
     187              : #define NUMERIC_HEADER_SIZE(n) \
     188              :     (VARHDRSZ + sizeof(uint16) + \
     189              :      (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
     190              : 
     191              : /*
     192              :  * Definitions for special values (NaN, positive infinity, negative infinity).
     193              :  *
     194              :  * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
     195              :  * infinity, 11 for negative infinity.  (This makes the sign bit match where
     196              :  * it is in a short-format value, though we make no use of that at present.)
     197              :  * We could mask off the remaining bits before testing the active bits, but
     198              :  * currently those bits must be zeroes, so masking would just add cycles.
     199              :  */
     200              : #define NUMERIC_EXT_SIGN_MASK   0xF000  /* high bits plus NaN/Inf flag bits */
     201              : #define NUMERIC_NAN             0xC000
     202              : #define NUMERIC_PINF            0xD000
     203              : #define NUMERIC_NINF            0xF000
     204              : #define NUMERIC_INF_SIGN_MASK   0x2000
     205              : 
     206              : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
     207              : #define NUMERIC_IS_NAN(n)       ((n)->choice.n_header == NUMERIC_NAN)
     208              : #define NUMERIC_IS_PINF(n)      ((n)->choice.n_header == NUMERIC_PINF)
     209              : #define NUMERIC_IS_NINF(n)      ((n)->choice.n_header == NUMERIC_NINF)
     210              : #define NUMERIC_IS_INF(n) \
     211              :     (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
     212              : 
     213              : /*
     214              :  * Short format definitions.
     215              :  */
     216              : 
     217              : #define NUMERIC_SHORT_SIGN_MASK         0x2000
     218              : #define NUMERIC_SHORT_DSCALE_MASK       0x1F80
     219              : #define NUMERIC_SHORT_DSCALE_SHIFT      7
     220              : #define NUMERIC_SHORT_DSCALE_MAX        \
     221              :     (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
     222              : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK  0x0040
     223              : #define NUMERIC_SHORT_WEIGHT_MASK       0x003F
     224              : #define NUMERIC_SHORT_WEIGHT_MAX        NUMERIC_SHORT_WEIGHT_MASK
     225              : #define NUMERIC_SHORT_WEIGHT_MIN        (-(NUMERIC_SHORT_WEIGHT_MASK+1))
     226              : 
     227              : /*
     228              :  * Extract sign, display scale, weight.  These macros extract field values
     229              :  * suitable for the NumericVar format from the Numeric (on-disk) format.
     230              :  *
     231              :  * Note that we don't trouble to ensure that dscale and weight read as zero
     232              :  * for an infinity; however, that doesn't matter since we never convert
     233              :  * "special" numerics to NumericVar form.  Only the constants defined below
     234              :  * (const_nan, etc) ever represent a non-finite value as a NumericVar.
     235              :  */
     236              : 
     237              : #define NUMERIC_DSCALE_MASK         0x3FFF
     238              : #define NUMERIC_DSCALE_MAX          NUMERIC_DSCALE_MASK
     239              : 
     240              : #define NUMERIC_SIGN(n) \
     241              :     (NUMERIC_IS_SHORT(n) ? \
     242              :         (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
     243              :          NUMERIC_NEG : NUMERIC_POS) : \
     244              :         (NUMERIC_IS_SPECIAL(n) ? \
     245              :          NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
     246              : #define NUMERIC_DSCALE(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
     247              :     ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
     248              :         >> NUMERIC_SHORT_DSCALE_SHIFT \
     249              :     : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
     250              : #define NUMERIC_WEIGHT(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
     251              :     (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
     252              :         ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
     253              :      | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
     254              :     : ((n)->choice.n_long.n_weight))
     255              : 
     256              : /*
     257              :  * Maximum weight of a stored Numeric value (based on the use of int16 for the
     258              :  * weight in NumericLong).  Note that intermediate values held in NumericVar
     259              :  * and NumericSumAccum variables may have much larger weights.
     260              :  */
     261              : #define NUMERIC_WEIGHT_MAX          PG_INT16_MAX
     262              : 
     263              : /* ----------
     264              :  * NumericVar is the format we use for arithmetic.  The digit-array part
     265              :  * is the same as the NumericData storage format, but the header is more
     266              :  * complex.
     267              :  *
     268              :  * The value represented by a NumericVar is determined by the sign, weight,
     269              :  * ndigits, and digits[] array.  If it is a "special" value (NaN or Inf)
     270              :  * then only the sign field matters; ndigits should be zero, and the weight
     271              :  * and dscale fields are ignored.
     272              :  *
     273              :  * Note: the first digit of a NumericVar's value is assumed to be multiplied
     274              :  * by NBASE ** weight.  Another way to say it is that there are weight+1
     275              :  * digits before the decimal point.  It is possible to have weight < 0.
     276              :  *
     277              :  * buf points at the physical start of the palloc'd digit buffer for the
     278              :  * NumericVar.  digits points at the first digit in actual use (the one
     279              :  * with the specified weight).  We normally leave an unused digit or two
     280              :  * (preset to zeroes) between buf and digits, so that there is room to store
     281              :  * a carry out of the top digit without reallocating space.  We just need to
     282              :  * decrement digits (and increment weight) to make room for the carry digit.
     283              :  * (There is no such extra space in a numeric value stored in the database,
     284              :  * only in a NumericVar in memory.)
     285              :  *
     286              :  * If buf is NULL then the digit buffer isn't actually palloc'd and should
     287              :  * not be freed --- see the constants below for an example.
     288              :  *
     289              :  * dscale, or display scale, is the nominal precision expressed as number
     290              :  * of digits after the decimal point (it must always be >= 0 at present).
     291              :  * dscale may be more than the number of physically stored fractional digits,
     292              :  * implying that we have suppressed storage of significant trailing zeroes.
     293              :  * It should never be less than the number of stored digits, since that would
     294              :  * imply hiding digits that are present.  NOTE that dscale is always expressed
     295              :  * in *decimal* digits, and so it may correspond to a fractional number of
     296              :  * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
     297              :  *
     298              :  * rscale, or result scale, is the target precision for a computation.
     299              :  * Like dscale it is expressed as number of *decimal* digits after the decimal
     300              :  * point, and is always >= 0 at present.
     301              :  * Note that rscale is not stored in variables --- it's figured on-the-fly
     302              :  * from the dscales of the inputs.
     303              :  *
     304              :  * While we consistently use "weight" to refer to the base-NBASE weight of
     305              :  * a numeric value, it is convenient in some scale-related calculations to
     306              :  * make use of the base-10 weight (ie, the approximate log10 of the value).
     307              :  * To avoid confusion, such a decimal-units weight is called a "dweight".
     308              :  *
     309              :  * NB: All the variable-level functions are written in a style that makes it
     310              :  * possible to give one and the same variable as argument and destination.
     311              :  * This is feasible because the digit buffer is separate from the variable.
     312              :  * ----------
     313              :  */
     314              : typedef struct NumericVar
     315              : {
     316              :     int         ndigits;        /* # of digits in digits[] - can be 0! */
     317              :     int         weight;         /* weight of first digit */
     318              :     int         sign;           /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
     319              :     int         dscale;         /* display scale */
     320              :     NumericDigit *buf;          /* start of palloc'd space for digits[] */
     321              :     NumericDigit *digits;       /* base-NBASE digits */
     322              : } NumericVar;
     323              : 
     324              : 
     325              : /* ----------
     326              :  * Data for generate_series
     327              :  * ----------
     328              :  */
     329              : typedef struct
     330              : {
     331              :     NumericVar  current;
     332              :     NumericVar  stop;
     333              :     NumericVar  step;
     334              : } generate_series_numeric_fctx;
     335              : 
     336              : 
     337              : /* ----------
     338              :  * Sort support.
     339              :  * ----------
     340              :  */
     341              : typedef struct
     342              : {
     343              :     void       *buf;            /* buffer for short varlenas */
     344              :     int64       input_count;    /* number of non-null values seen */
     345              :     bool        estimating;     /* true if estimating cardinality */
     346              : 
     347              :     hyperLogLogState abbr_card; /* cardinality estimator */
     348              : } NumericSortSupport;
     349              : 
     350              : 
     351              : /* ----------
     352              :  * Fast sum accumulator.
     353              :  *
     354              :  * NumericSumAccum is used to implement SUM(), and other standard aggregates
     355              :  * that track the sum of input values.  It uses 32-bit integers to store the
     356              :  * digits, instead of the normal 16-bit integers (with NBASE=10000).  This
     357              :  * way, we can safely accumulate up to NBASE - 1 values without propagating
     358              :  * carry, before risking overflow of any of the digits.  'num_uncarried'
     359              :  * tracks how many values have been accumulated without propagating carry.
     360              :  *
     361              :  * Positive and negative values are accumulated separately, in 'pos_digits'
     362              :  * and 'neg_digits'.  This is simpler and faster than deciding whether to add
     363              :  * or subtract from the current value, for each new value (see sub_var() for
     364              :  * the logic we avoid by doing this).  Both buffers are of same size, and
     365              :  * have the same weight and scale.  In accum_sum_final(), the positive and
     366              :  * negative sums are added together to produce the final result.
     367              :  *
     368              :  * When a new value has a larger ndigits or weight than the accumulator
     369              :  * currently does, the accumulator is enlarged to accommodate the new value.
     370              :  * We normally have one zero digit reserved for carry propagation, and that
     371              :  * is indicated by the 'have_carry_space' flag.  When accum_sum_carry() uses
     372              :  * up the reserved digit, it clears the 'have_carry_space' flag.  The next
     373              :  * call to accum_sum_add() will enlarge the buffer, to make room for the
     374              :  * extra digit, and set the flag again.
     375              :  *
     376              :  * To initialize a new accumulator, simply reset all fields to zeros.
     377              :  *
     378              :  * The accumulator does not handle NaNs.
     379              :  * ----------
     380              :  */
     381              : typedef struct NumericSumAccum
     382              : {
     383              :     int         ndigits;
     384              :     int         weight;
     385              :     int         dscale;
     386              :     int         num_uncarried;
     387              :     bool        have_carry_space;
     388              :     int32      *pos_digits;
     389              :     int32      *neg_digits;
     390              : } NumericSumAccum;
     391              : 
     392              : 
     393              : /*
     394              :  * We define our own macros for packing and unpacking abbreviated-key
     395              :  * representations, just to have a notational indication that that's
     396              :  * what we're doing.  Now that sizeof(Datum) is always 8, we can rely
     397              :  * on fitting an int64 into Datum.
     398              :  *
     399              :  * The range of abbreviations for finite values is from +PG_INT64_MAX
     400              :  * to -PG_INT64_MAX.  NaN has the abbreviation PG_INT64_MIN, and we
     401              :  * define the sort ordering to make that work out properly (see further
     402              :  * comments below).  PINF and NINF share the abbreviations of the largest
     403              :  * and smallest finite abbreviation classes.
     404              :  */
     405              : #define NumericAbbrevGetDatum(X) Int64GetDatum(X)
     406              : #define DatumGetNumericAbbrev(X) DatumGetInt64(X)
     407              : #define NUMERIC_ABBREV_NAN       NumericAbbrevGetDatum(PG_INT64_MIN)
     408              : #define NUMERIC_ABBREV_PINF      NumericAbbrevGetDatum(-PG_INT64_MAX)
     409              : #define NUMERIC_ABBREV_NINF      NumericAbbrevGetDatum(PG_INT64_MAX)
     410              : 
     411              : 
     412              : /* ----------
     413              :  * Some preinitialized constants
     414              :  * ----------
     415              :  */
     416              : static const NumericDigit const_zero_data[1] = {0};
     417              : static const NumericVar const_zero =
     418              : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
     419              : 
     420              : static const NumericDigit const_one_data[1] = {1};
     421              : static const NumericVar const_one =
     422              : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
     423              : 
     424              : static const NumericVar const_minus_one =
     425              : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
     426              : 
     427              : static const NumericDigit const_two_data[1] = {2};
     428              : static const NumericVar const_two =
     429              : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
     430              : 
     431              : #if DEC_DIGITS == 4
     432              : static const NumericDigit const_zero_point_nine_data[1] = {9000};
     433              : #elif DEC_DIGITS == 2
     434              : static const NumericDigit const_zero_point_nine_data[1] = {90};
     435              : #elif DEC_DIGITS == 1
     436              : static const NumericDigit const_zero_point_nine_data[1] = {9};
     437              : #endif
     438              : static const NumericVar const_zero_point_nine =
     439              : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
     440              : 
     441              : #if DEC_DIGITS == 4
     442              : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
     443              : #elif DEC_DIGITS == 2
     444              : static const NumericDigit const_one_point_one_data[2] = {1, 10};
     445              : #elif DEC_DIGITS == 1
     446              : static const NumericDigit const_one_point_one_data[2] = {1, 1};
     447              : #endif
     448              : static const NumericVar const_one_point_one =
     449              : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
     450              : 
     451              : static const NumericVar const_nan =
     452              : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
     453              : 
     454              : static const NumericVar const_pinf =
     455              : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
     456              : 
     457              : static const NumericVar const_ninf =
     458              : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
     459              : 
     460              : #if DEC_DIGITS == 4
     461              : static const int round_powers[4] = {0, 1000, 100, 10};
     462              : #endif
     463              : 
     464              : 
     465              : /* ----------
     466              :  * Local functions
     467              :  * ----------
     468              :  */
     469              : 
     470              : #ifdef NUMERIC_DEBUG
     471              : static void dump_numeric(const char *str, Numeric num);
     472              : static void dump_var(const char *str, NumericVar *var);
     473              : #else
     474              : #define dump_numeric(s,n)
     475              : #define dump_var(s,v)
     476              : #endif
     477              : 
     478              : #define digitbuf_alloc(ndigits)  \
     479              :     ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
     480              : #define digitbuf_free(buf)  \
     481              :     do { \
     482              :          if ((buf) != NULL) \
     483              :              pfree(buf); \
     484              :     } while (0)
     485              : 
     486              : #define init_var(v)     memset(v, 0, sizeof(NumericVar))
     487              : 
     488              : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
     489              :     (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
     490              : #define NUMERIC_NDIGITS(num) \
     491              :     ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
     492              : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
     493              :     ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
     494              :     (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
     495              :     (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
     496              : 
     497              : static void alloc_var(NumericVar *var, int ndigits);
     498              : static void free_var(NumericVar *var);
     499              : static void zero_var(NumericVar *var);
     500              : 
     501              : static bool set_var_from_str(const char *str, const char *cp,
     502              :                              NumericVar *dest, const char **endptr,
     503              :                              Node *escontext);
     504              : static bool set_var_from_non_decimal_integer_str(const char *str,
     505              :                                                  const char *cp, int sign,
     506              :                                                  int base, NumericVar *dest,
     507              :                                                  const char **endptr,
     508              :                                                  Node *escontext);
     509              : static void set_var_from_num(Numeric num, NumericVar *dest);
     510              : static void init_var_from_num(Numeric num, NumericVar *dest);
     511              : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
     512              : static char *get_str_from_var(const NumericVar *var);
     513              : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
     514              : 
     515              : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
     516              : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
     517              : 
     518              : static Numeric duplicate_numeric(Numeric num);
     519              : static Numeric make_result(const NumericVar *var);
     520              : static Numeric make_result_safe(const NumericVar *var, Node *escontext);
     521              : 
     522              : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
     523              : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
     524              : 
     525              : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
     526              : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
     527              : static void int64_to_numericvar(int64 val, NumericVar *var);
     528              : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
     529              : static void int128_to_numericvar(INT128 val, NumericVar *var);
     530              : static double numericvar_to_double_no_overflow(const NumericVar *var);
     531              : 
     532              : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
     533              : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
     534              : static int  numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
     535              : static int  numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
     536              : 
     537              : static Datum numeric_abbrev_convert_var(const NumericVar *var,
     538              :                                         NumericSortSupport *nss);
     539              : 
     540              : static int  cmp_numerics(Numeric num1, Numeric num2);
     541              : static int  cmp_var(const NumericVar *var1, const NumericVar *var2);
     542              : static int  cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
     543              :                            int var1weight, int var1sign,
     544              :                            const NumericDigit *var2digits, int var2ndigits,
     545              :                            int var2weight, int var2sign);
     546              : static void add_var(const NumericVar *var1, const NumericVar *var2,
     547              :                     NumericVar *result);
     548              : static void sub_var(const NumericVar *var1, const NumericVar *var2,
     549              :                     NumericVar *result);
     550              : static void mul_var(const NumericVar *var1, const NumericVar *var2,
     551              :                     NumericVar *result,
     552              :                     int rscale);
     553              : static void mul_var_short(const NumericVar *var1, const NumericVar *var2,
     554              :                           NumericVar *result);
     555              : static void div_var(const NumericVar *var1, const NumericVar *var2,
     556              :                     NumericVar *result, int rscale, bool round, bool exact);
     557              : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
     558              :                         NumericVar *result, int rscale, bool round);
     559              : #ifdef HAVE_INT128
     560              : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
     561              :                           NumericVar *result, int rscale, bool round);
     562              : #endif
     563              : static int  select_div_scale(const NumericVar *var1, const NumericVar *var2);
     564              : static void mod_var(const NumericVar *var1, const NumericVar *var2,
     565              :                     NumericVar *result);
     566              : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
     567              :                         NumericVar *quot, NumericVar *rem);
     568              : static void ceil_var(const NumericVar *var, NumericVar *result);
     569              : static void floor_var(const NumericVar *var, NumericVar *result);
     570              : 
     571              : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
     572              :                     NumericVar *result);
     573              : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
     574              : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
     575              : static int  estimate_ln_dweight(const NumericVar *var);
     576              : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
     577              : static void log_var(const NumericVar *base, const NumericVar *num,
     578              :                     NumericVar *result);
     579              : static void power_var(const NumericVar *base, const NumericVar *exp,
     580              :                       NumericVar *result);
     581              : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
     582              :                           NumericVar *result);
     583              : static void power_ten_int(int exp, NumericVar *result);
     584              : static void random_var(pg_prng_state *state, const NumericVar *rmin,
     585              :                        const NumericVar *rmax, NumericVar *result);
     586              : 
     587              : static int  cmp_abs(const NumericVar *var1, const NumericVar *var2);
     588              : static int  cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
     589              :                            int var1weight,
     590              :                            const NumericDigit *var2digits, int var2ndigits,
     591              :                            int var2weight);
     592              : static void add_abs(const NumericVar *var1, const NumericVar *var2,
     593              :                     NumericVar *result);
     594              : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
     595              :                     NumericVar *result);
     596              : static void round_var(NumericVar *var, int rscale);
     597              : static void trunc_var(NumericVar *var, int rscale);
     598              : static void strip_var(NumericVar *var);
     599              : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
     600              :                            const NumericVar *count_var,
     601              :                            NumericVar *result_var);
     602              : 
     603              : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
     604              : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
     605              : static void accum_sum_carry(NumericSumAccum *accum);
     606              : static void accum_sum_reset(NumericSumAccum *accum);
     607              : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
     608              : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
     609              : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
     610              : 
     611              : 
     612              : /* ----------------------------------------------------------------------
     613              :  *
     614              :  * Input-, output- and rounding-functions
     615              :  *
     616              :  * ----------------------------------------------------------------------
     617              :  */
     618              : 
     619              : 
     620              : /*
     621              :  * numeric_in() -
     622              :  *
     623              :  *  Input function for numeric data type
     624              :  */
     625              : Datum
     626        83152 : numeric_in(PG_FUNCTION_ARGS)
     627              : {
     628        83152 :     char       *str = PG_GETARG_CSTRING(0);
     629              : #ifdef NOT_USED
     630              :     Oid         typelem = PG_GETARG_OID(1);
     631              : #endif
     632        83152 :     int32       typmod = PG_GETARG_INT32(2);
     633        83152 :     Node       *escontext = fcinfo->context;
     634              :     Numeric     res;
     635              :     const char *cp;
     636              :     const char *numstart;
     637              :     int         sign;
     638              : 
     639              :     /* Skip leading spaces */
     640        83152 :     cp = str;
     641        95362 :     while (*cp)
     642              :     {
     643        95353 :         if (!isspace((unsigned char) *cp))
     644        83143 :             break;
     645        12210 :         cp++;
     646              :     }
     647              : 
     648              :     /*
     649              :      * Process the number's sign. This duplicates logic in set_var_from_str(),
     650              :      * but it's worth doing here, since it simplifies the handling of
     651              :      * infinities and non-decimal integers.
     652              :      */
     653        83152 :     numstart = cp;
     654        83152 :     sign = NUMERIC_POS;
     655              : 
     656        83152 :     if (*cp == '+')
     657           24 :         cp++;
     658        83128 :     else if (*cp == '-')
     659              :     {
     660         2063 :         sign = NUMERIC_NEG;
     661         2063 :         cp++;
     662              :     }
     663              : 
     664              :     /*
     665              :      * Check for NaN and infinities.  We recognize the same strings allowed by
     666              :      * float8in().
     667              :      *
     668              :      * Since all other legal inputs have a digit or a decimal point after the
     669              :      * sign, we need only check for NaN/infinity if that's not the case.
     670              :      */
     671        83152 :     if (!isdigit((unsigned char) *cp) && *cp != '.')
     672              :     {
     673              :         /*
     674              :          * The number must be NaN or infinity; anything else can only be a
     675              :          * syntax error. Note that NaN mustn't have a sign.
     676              :          */
     677          898 :         if (pg_strncasecmp(numstart, "NaN", 3) == 0)
     678              :         {
     679          303 :             res = make_result(&const_nan);
     680          303 :             cp = numstart + 3;
     681              :         }
     682          595 :         else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
     683              :         {
     684          246 :             res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
     685          246 :             cp += 8;
     686              :         }
     687          349 :         else if (pg_strncasecmp(cp, "inf", 3) == 0)
     688              :         {
     689          294 :             res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
     690          294 :             cp += 3;
     691              :         }
     692              :         else
     693           55 :             goto invalid_syntax;
     694              : 
     695              :         /*
     696              :          * Check for trailing junk; there should be nothing left but spaces.
     697              :          *
     698              :          * We intentionally do this check before applying the typmod because
     699              :          * we would like to throw any trailing-junk syntax error before any
     700              :          * semantic error resulting from apply_typmod_special().
     701              :          */
     702          864 :         while (*cp)
     703              :         {
     704           21 :             if (!isspace((unsigned char) *cp))
     705            0 :                 goto invalid_syntax;
     706           21 :             cp++;
     707              :         }
     708              : 
     709          843 :         if (!apply_typmod_special(res, typmod, escontext))
     710            0 :             PG_RETURN_NULL();
     711              :     }
     712              :     else
     713              :     {
     714              :         /*
     715              :          * We have a normal numeric value, which may be a non-decimal integer
     716              :          * or a regular decimal number.
     717              :          */
     718              :         NumericVar  value;
     719              :         int         base;
     720              : 
     721        82254 :         init_var(&value);
     722              : 
     723              :         /*
     724              :          * Determine the number's base by looking for a non-decimal prefix
     725              :          * indicator ("0x", "0o", or "0b").
     726              :          */
     727        82254 :         if (cp[0] == '0')
     728              :         {
     729        25454 :             switch (cp[1])
     730              :             {
     731           36 :                 case 'x':
     732              :                 case 'X':
     733           36 :                     base = 16;
     734           36 :                     break;
     735           21 :                 case 'o':
     736              :                 case 'O':
     737           21 :                     base = 8;
     738           21 :                     break;
     739           21 :                 case 'b':
     740              :                 case 'B':
     741           21 :                     base = 2;
     742           21 :                     break;
     743        25376 :                 default:
     744        25376 :                     base = 10;
     745              :             }
     746              :         }
     747              :         else
     748        56800 :             base = 10;
     749              : 
     750              :         /* Parse the rest of the number and apply the sign */
     751        82254 :         if (base == 10)
     752              :         {
     753        82176 :             if (!set_var_from_str(str, cp, &value, &cp, escontext))
     754           12 :                 PG_RETURN_NULL();
     755        82152 :             value.sign = sign;
     756              :         }
     757              :         else
     758              :         {
     759           78 :             if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
     760              :                                                       &value, &cp, escontext))
     761            0 :                 PG_RETURN_NULL();
     762              :         }
     763              : 
     764              :         /*
     765              :          * Should be nothing left but spaces. As above, throw any typmod error
     766              :          * after finishing syntax check.
     767              :          */
     768        82260 :         while (*cp)
     769              :         {
     770           75 :             if (!isspace((unsigned char) *cp))
     771           36 :                 goto invalid_syntax;
     772           39 :             cp++;
     773              :         }
     774              : 
     775        82185 :         if (!apply_typmod(&value, typmod, escontext))
     776           12 :             PG_RETURN_NULL();
     777              : 
     778        82173 :         res = make_result_safe(&value, escontext);
     779              : 
     780        82173 :         free_var(&value);
     781              :     }
     782              : 
     783        83016 :     PG_RETURN_NUMERIC(res);
     784              : 
     785           91 : invalid_syntax:
     786           91 :     ereturn(escontext, (Datum) 0,
     787              :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     788              :              errmsg("invalid input syntax for type %s: \"%s\"",
     789              :                     "numeric", str)));
     790              : }
     791              : 
     792              : 
     793              : /*
     794              :  * numeric_out() -
     795              :  *
     796              :  *  Output function for numeric data type
     797              :  */
     798              : Datum
     799       427088 : numeric_out(PG_FUNCTION_ARGS)
     800              : {
     801       427088 :     Numeric     num = PG_GETARG_NUMERIC(0);
     802              :     NumericVar  x;
     803              :     char       *str;
     804              : 
     805              :     /*
     806              :      * Handle NaN and infinities
     807              :      */
     808       427088 :     if (NUMERIC_IS_SPECIAL(num))
     809              :     {
     810         1806 :         if (NUMERIC_IS_PINF(num))
     811          520 :             PG_RETURN_CSTRING(pstrdup("Infinity"));
     812         1286 :         else if (NUMERIC_IS_NINF(num))
     813          329 :             PG_RETURN_CSTRING(pstrdup("-Infinity"));
     814              :         else
     815          957 :             PG_RETURN_CSTRING(pstrdup("NaN"));
     816              :     }
     817              : 
     818              :     /*
     819              :      * Get the number in the variable format.
     820              :      */
     821       425282 :     init_var_from_num(num, &x);
     822              : 
     823       425282 :     str = get_str_from_var(&x);
     824              : 
     825       425282 :     PG_RETURN_CSTRING(str);
     826              : }
     827              : 
     828              : /*
     829              :  * numeric_is_nan() -
     830              :  *
     831              :  *  Is Numeric value a NaN?
     832              :  */
     833              : bool
     834         4210 : numeric_is_nan(Numeric num)
     835              : {
     836         4210 :     return NUMERIC_IS_NAN(num);
     837              : }
     838              : 
     839              : /*
     840              :  * numeric_is_inf() -
     841              :  *
     842              :  *  Is Numeric value an infinity?
     843              :  */
     844              : bool
     845          605 : numeric_is_inf(Numeric num)
     846              : {
     847          605 :     return NUMERIC_IS_INF(num);
     848              : }
     849              : 
     850              : /*
     851              :  * numeric_is_integral() -
     852              :  *
     853              :  *  Is Numeric value integral?
     854              :  */
     855              : static bool
     856           33 : numeric_is_integral(Numeric num)
     857              : {
     858              :     NumericVar  arg;
     859              : 
     860              :     /* Reject NaN, but infinities are considered integral */
     861           33 :     if (NUMERIC_IS_SPECIAL(num))
     862              :     {
     863           15 :         if (NUMERIC_IS_NAN(num))
     864            0 :             return false;
     865           15 :         return true;
     866              :     }
     867              : 
     868              :     /* Integral if there are no digits to the right of the decimal point */
     869           18 :     init_var_from_num(num, &arg);
     870              : 
     871           18 :     return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
     872              : }
     873              : 
     874              : /*
     875              :  * make_numeric_typmod() -
     876              :  *
     877              :  *  Pack numeric precision and scale values into a typmod.  The upper 16 bits
     878              :  *  are used for the precision (though actually not all these bits are needed,
     879              :  *  since the maximum allowed precision is 1000).  The lower 16 bits are for
     880              :  *  the scale, but since the scale is constrained to the range [-1000, 1000],
     881              :  *  we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
     882              :  *  unset, for possible future use.
     883              :  *
     884              :  *  For purely historical reasons VARHDRSZ is then added to the result, thus
     885              :  *  the unused space in the upper 16 bits is not all as freely available as it
     886              :  *  might seem.  (We can't let the result overflow to a negative int32, as
     887              :  *  other parts of the system would interpret that as not-a-valid-typmod.)
     888              :  */
     889              : static inline int32
     890          947 : make_numeric_typmod(int precision, int scale)
     891              : {
     892          947 :     return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
     893              : }
     894              : 
     895              : /*
     896              :  * Because of the offset, valid numeric typmods are at least VARHDRSZ
     897              :  */
     898              : static inline bool
     899        94702 : is_valid_numeric_typmod(int32 typmod)
     900              : {
     901        94702 :     return typmod >= (int32) VARHDRSZ;
     902              : }
     903              : 
     904              : /*
     905              :  * numeric_typmod_precision() -
     906              :  *
     907              :  *  Extract the precision from a numeric typmod --- see make_numeric_typmod().
     908              :  */
     909              : static inline int
     910        24310 : numeric_typmod_precision(int32 typmod)
     911              : {
     912        24310 :     return ((typmod - VARHDRSZ) >> 16) & 0xffff;
     913              : }
     914              : 
     915              : /*
     916              :  * numeric_typmod_scale() -
     917              :  *
     918              :  *  Extract the scale from a numeric typmod --- see make_numeric_typmod().
     919              :  *
     920              :  *  Note that the scale may be negative, so we must do sign extension when
     921              :  *  unpacking it.  We do this using the bit hack (x^1024)-1024, which sign
     922              :  *  extends an 11-bit two's complement number x.
     923              :  */
     924              : static inline int
     925        20763 : numeric_typmod_scale(int32 typmod)
     926              : {
     927        20763 :     return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
     928              : }
     929              : 
     930              : /*
     931              :  * numeric_maximum_size() -
     932              :  *
     933              :  *  Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
     934              :  */
     935              : int32
     936         3547 : numeric_maximum_size(int32 typmod)
     937              : {
     938              :     int         precision;
     939              :     int         numeric_digits;
     940              : 
     941         3547 :     if (!is_valid_numeric_typmod(typmod))
     942            0 :         return -1;
     943              : 
     944              :     /* precision (ie, max # of digits) is in upper bits of typmod */
     945         3547 :     precision = numeric_typmod_precision(typmod);
     946              : 
     947              :     /*
     948              :      * This formula computes the maximum number of NumericDigits we could need
     949              :      * in order to store the specified number of decimal digits. Because the
     950              :      * weight is stored as a number of NumericDigits rather than a number of
     951              :      * decimal digits, it's possible that the first NumericDigit will contain
     952              :      * only a single decimal digit.  Thus, the first two decimal digits can
     953              :      * require two NumericDigits to store, but it isn't until we reach
     954              :      * DEC_DIGITS + 2 decimal digits that we potentially need a third
     955              :      * NumericDigit.
     956              :      */
     957         3547 :     numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
     958              : 
     959              :     /*
     960              :      * In most cases, the size of a numeric will be smaller than the value
     961              :      * computed below, because the varlena header will typically get toasted
     962              :      * down to a single byte before being stored on disk, and it may also be
     963              :      * possible to use a short numeric header.  But our job here is to compute
     964              :      * the worst case.
     965              :      */
     966         3547 :     return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
     967              : }
     968              : 
     969              : /*
     970              :  * numeric_out_sci() -
     971              :  *
     972              :  *  Output function for numeric data type in scientific notation.
     973              :  */
     974              : char *
     975          123 : numeric_out_sci(Numeric num, int scale)
     976              : {
     977              :     NumericVar  x;
     978              :     char       *str;
     979              : 
     980              :     /*
     981              :      * Handle NaN and infinities
     982              :      */
     983          123 :     if (NUMERIC_IS_SPECIAL(num))
     984              :     {
     985            9 :         if (NUMERIC_IS_PINF(num))
     986            3 :             return pstrdup("Infinity");
     987            6 :         else if (NUMERIC_IS_NINF(num))
     988            3 :             return pstrdup("-Infinity");
     989              :         else
     990            3 :             return pstrdup("NaN");
     991              :     }
     992              : 
     993          114 :     init_var_from_num(num, &x);
     994              : 
     995          114 :     str = get_str_from_var_sci(&x, scale);
     996              : 
     997          114 :     return str;
     998              : }
     999              : 
    1000              : /*
    1001              :  * numeric_normalize() -
    1002              :  *
    1003              :  *  Output function for numeric data type, suppressing insignificant trailing
    1004              :  *  zeroes and then any trailing decimal point.  The intent of this is to
    1005              :  *  produce strings that are equal if and only if the input numeric values
    1006              :  *  compare equal.
    1007              :  */
    1008              : char *
    1009        24702 : numeric_normalize(Numeric num)
    1010              : {
    1011              :     NumericVar  x;
    1012              :     char       *str;
    1013              :     int         last;
    1014              : 
    1015              :     /*
    1016              :      * Handle NaN and infinities
    1017              :      */
    1018        24702 :     if (NUMERIC_IS_SPECIAL(num))
    1019              :     {
    1020            0 :         if (NUMERIC_IS_PINF(num))
    1021            0 :             return pstrdup("Infinity");
    1022            0 :         else if (NUMERIC_IS_NINF(num))
    1023            0 :             return pstrdup("-Infinity");
    1024              :         else
    1025            0 :             return pstrdup("NaN");
    1026              :     }
    1027              : 
    1028        24702 :     init_var_from_num(num, &x);
    1029              : 
    1030        24702 :     str = get_str_from_var(&x);
    1031              : 
    1032              :     /* If there's no decimal point, there's certainly nothing to remove. */
    1033        24702 :     if (strchr(str, '.') != NULL)
    1034              :     {
    1035              :         /*
    1036              :          * Back up over trailing fractional zeroes.  Since there is a decimal
    1037              :          * point, this loop will terminate safely.
    1038              :          */
    1039           21 :         last = strlen(str) - 1;
    1040           42 :         while (str[last] == '0')
    1041           21 :             last--;
    1042              : 
    1043              :         /* We want to get rid of the decimal point too, if it's now last. */
    1044           21 :         if (str[last] == '.')
    1045           21 :             last--;
    1046              : 
    1047              :         /* Delete whatever we backed up over. */
    1048           21 :         str[last + 1] = '\0';
    1049              :     }
    1050              : 
    1051        24702 :     return str;
    1052              : }
    1053              : 
    1054              : /*
    1055              :  *      numeric_recv            - converts external binary format to numeric
    1056              :  *
    1057              :  * External format is a sequence of int16's:
    1058              :  * ndigits, weight, sign, dscale, NumericDigits.
    1059              :  */
    1060              : Datum
    1061           51 : numeric_recv(PG_FUNCTION_ARGS)
    1062              : {
    1063           51 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
    1064              : 
    1065              : #ifdef NOT_USED
    1066              :     Oid         typelem = PG_GETARG_OID(1);
    1067              : #endif
    1068           51 :     int32       typmod = PG_GETARG_INT32(2);
    1069              :     NumericVar  value;
    1070              :     Numeric     res;
    1071              :     int         len,
    1072              :                 i;
    1073              : 
    1074           51 :     init_var(&value);
    1075              : 
    1076           51 :     len = (uint16) pq_getmsgint(buf, sizeof(uint16));
    1077              : 
    1078           51 :     alloc_var(&value, len);
    1079              : 
    1080           51 :     value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
    1081              :     /* we allow any int16 for weight --- OK? */
    1082              : 
    1083           51 :     value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
    1084           51 :     if (!(value.sign == NUMERIC_POS ||
    1085            0 :           value.sign == NUMERIC_NEG ||
    1086            0 :           value.sign == NUMERIC_NAN ||
    1087            0 :           value.sign == NUMERIC_PINF ||
    1088            0 :           value.sign == NUMERIC_NINF))
    1089            0 :         ereport(ERROR,
    1090              :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1091              :                  errmsg("invalid sign in external \"numeric\" value")));
    1092              : 
    1093           51 :     value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
    1094           51 :     if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
    1095            0 :         ereport(ERROR,
    1096              :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1097              :                  errmsg("invalid scale in external \"numeric\" value")));
    1098              : 
    1099          137 :     for (i = 0; i < len; i++)
    1100              :     {
    1101           86 :         NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
    1102              : 
    1103           86 :         if (d < 0 || d >= NBASE)
    1104            0 :             ereport(ERROR,
    1105              :                     (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1106              :                      errmsg("invalid digit in external \"numeric\" value")));
    1107           86 :         value.digits[i] = d;
    1108              :     }
    1109              : 
    1110              :     /*
    1111              :      * If the given dscale would hide any digits, truncate those digits away.
    1112              :      * We could alternatively throw an error, but that would take a bunch of
    1113              :      * extra code (about as much as trunc_var involves), and it might cause
    1114              :      * client compatibility issues.  Be careful not to apply trunc_var to
    1115              :      * special values, as it could do the wrong thing; we don't need it
    1116              :      * anyway, since make_result will ignore all but the sign field.
    1117              :      *
    1118              :      * After doing that, be sure to check the typmod restriction.
    1119              :      */
    1120           51 :     if (value.sign == NUMERIC_POS ||
    1121            0 :         value.sign == NUMERIC_NEG)
    1122              :     {
    1123           51 :         trunc_var(&value, value.dscale);
    1124              : 
    1125           51 :         (void) apply_typmod(&value, typmod, NULL);
    1126              : 
    1127           51 :         res = make_result(&value);
    1128              :     }
    1129              :     else
    1130              :     {
    1131              :         /* apply_typmod_special wants us to make the Numeric first */
    1132            0 :         res = make_result(&value);
    1133              : 
    1134            0 :         (void) apply_typmod_special(res, typmod, NULL);
    1135              :     }
    1136              : 
    1137           51 :     free_var(&value);
    1138              : 
    1139           51 :     PG_RETURN_NUMERIC(res);
    1140              : }
    1141              : 
    1142              : /*
    1143              :  *      numeric_send            - converts numeric to binary format
    1144              :  */
    1145              : Datum
    1146           35 : numeric_send(PG_FUNCTION_ARGS)
    1147              : {
    1148           35 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1149              :     NumericVar  x;
    1150              :     StringInfoData buf;
    1151              :     int         i;
    1152              : 
    1153           35 :     init_var_from_num(num, &x);
    1154              : 
    1155           35 :     pq_begintypsend(&buf);
    1156              : 
    1157           35 :     pq_sendint16(&buf, x.ndigits);
    1158           35 :     pq_sendint16(&buf, x.weight);
    1159           35 :     pq_sendint16(&buf, x.sign);
    1160           35 :     pq_sendint16(&buf, x.dscale);
    1161           97 :     for (i = 0; i < x.ndigits; i++)
    1162           62 :         pq_sendint16(&buf, x.digits[i]);
    1163              : 
    1164           35 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
    1165              : }
    1166              : 
    1167              : 
    1168              : /*
    1169              :  * numeric_support()
    1170              :  *
    1171              :  * Planner support function for the numeric() length coercion function.
    1172              :  *
    1173              :  * Flatten calls that solely represent increases in allowable precision.
    1174              :  * Scale changes mutate every datum, so they are unoptimizable.  Some values,
    1175              :  * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
    1176              :  * an unconstrained numeric to any constrained numeric is also unoptimizable.
    1177              :  */
    1178              : Datum
    1179          258 : numeric_support(PG_FUNCTION_ARGS)
    1180              : {
    1181          258 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1182          258 :     Node       *ret = NULL;
    1183              : 
    1184          258 :     if (IsA(rawreq, SupportRequestSimplify))
    1185              :     {
    1186          114 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
    1187          114 :         FuncExpr   *expr = req->fcall;
    1188              :         Node       *typmod;
    1189              : 
    1190              :         Assert(list_length(expr->args) >= 2);
    1191              : 
    1192          114 :         typmod = (Node *) lsecond(expr->args);
    1193              : 
    1194          114 :         if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
    1195              :         {
    1196          114 :             Node       *source = (Node *) linitial(expr->args);
    1197          114 :             int32       old_typmod = exprTypmod(source);
    1198          114 :             int32       new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
    1199          114 :             int32       old_scale = numeric_typmod_scale(old_typmod);
    1200          114 :             int32       new_scale = numeric_typmod_scale(new_typmod);
    1201          114 :             int32       old_precision = numeric_typmod_precision(old_typmod);
    1202          114 :             int32       new_precision = numeric_typmod_precision(new_typmod);
    1203              : 
    1204              :             /*
    1205              :              * If new_typmod is invalid, the destination is unconstrained;
    1206              :              * that's always OK.  If old_typmod is valid, the source is
    1207              :              * constrained, and we're OK if the scale is unchanged and the
    1208              :              * precision is not decreasing.  See further notes in function
    1209              :              * header comment.
    1210              :              */
    1211          228 :             if (!is_valid_numeric_typmod(new_typmod) ||
    1212          120 :                 (is_valid_numeric_typmod(old_typmod) &&
    1213            3 :                  new_scale == old_scale && new_precision >= old_precision))
    1214            3 :                 ret = relabel_to_typmod(source, new_typmod);
    1215              :         }
    1216              :     }
    1217              : 
    1218          258 :     PG_RETURN_POINTER(ret);
    1219              : }
    1220              : 
    1221              : /*
    1222              :  * numeric() -
    1223              :  *
    1224              :  *  This is a special function called by the Postgres database system
    1225              :  *  before a value is stored in a tuple's attribute. The precision and
    1226              :  *  scale of the attribute have to be applied on the value.
    1227              :  */
    1228              : Datum
    1229         5865 : numeric     (PG_FUNCTION_ARGS)
    1230              : {
    1231         5865 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1232         5865 :     int32       typmod = PG_GETARG_INT32(1);
    1233              :     Numeric     new;
    1234              :     int         precision;
    1235              :     int         scale;
    1236              :     int         ddigits;
    1237              :     int         maxdigits;
    1238              :     int         dscale;
    1239              :     NumericVar  var;
    1240              : 
    1241              :     /*
    1242              :      * Handle NaN and infinities: if apply_typmod_special doesn't complain,
    1243              :      * just return a copy of the input.
    1244              :      */
    1245         5865 :     if (NUMERIC_IS_SPECIAL(num))
    1246              :     {
    1247          105 :         (void) apply_typmod_special(num, typmod, NULL);
    1248           96 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    1249              :     }
    1250              : 
    1251              :     /*
    1252              :      * If the value isn't a valid type modifier, simply return a copy of the
    1253              :      * input value
    1254              :      */
    1255         5760 :     if (!is_valid_numeric_typmod(typmod))
    1256            0 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    1257              : 
    1258              :     /*
    1259              :      * Get the precision and scale out of the typmod value
    1260              :      */
    1261         5760 :     precision = numeric_typmod_precision(typmod);
    1262         5760 :     scale = numeric_typmod_scale(typmod);
    1263         5760 :     maxdigits = precision - scale;
    1264              : 
    1265              :     /* The target display scale is non-negative */
    1266         5760 :     dscale = Max(scale, 0);
    1267              : 
    1268              :     /*
    1269              :      * If the number is certainly in bounds and due to the target scale no
    1270              :      * rounding could be necessary, just make a copy of the input and modify
    1271              :      * its scale fields, unless the larger scale forces us to abandon the
    1272              :      * short representation.  (Note we assume the existing dscale is
    1273              :      * honest...)
    1274              :      */
    1275         5760 :     ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
    1276         5760 :     if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
    1277         3566 :         && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
    1278            0 :             || !NUMERIC_IS_SHORT(num)))
    1279              :     {
    1280         3566 :         new = duplicate_numeric(num);
    1281         3566 :         if (NUMERIC_IS_SHORT(num))
    1282         3566 :             new->choice.n_short.n_header =
    1283         3566 :                 (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
    1284         3566 :                 | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
    1285              :         else
    1286            0 :             new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
    1287            0 :                 ((uint16) dscale & NUMERIC_DSCALE_MASK);
    1288         3566 :         PG_RETURN_NUMERIC(new);
    1289              :     }
    1290              : 
    1291              :     /*
    1292              :      * We really need to fiddle with things - unpack the number into a
    1293              :      * variable and let apply_typmod() do it.
    1294              :      */
    1295         2194 :     init_var(&var);
    1296              : 
    1297         2194 :     set_var_from_num(num, &var);
    1298         2194 :     (void) apply_typmod(&var, typmod, NULL);
    1299         2164 :     new = make_result(&var);
    1300              : 
    1301         2164 :     free_var(&var);
    1302              : 
    1303         2164 :     PG_RETURN_NUMERIC(new);
    1304              : }
    1305              : 
    1306              : Datum
    1307          968 : numerictypmodin(PG_FUNCTION_ARGS)
    1308              : {
    1309          968 :     ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
    1310              :     int32      *tl;
    1311              :     int         n;
    1312              :     int32       typmod;
    1313              : 
    1314          968 :     tl = ArrayGetIntegerTypmods(ta, &n);
    1315              : 
    1316          968 :     if (n == 2)
    1317              :     {
    1318          958 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
    1319            9 :             ereport(ERROR,
    1320              :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1321              :                      errmsg("NUMERIC precision %d must be between 1 and %d",
    1322              :                             tl[0], NUMERIC_MAX_PRECISION)));
    1323          949 :         if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
    1324            6 :             ereport(ERROR,
    1325              :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1326              :                      errmsg("NUMERIC scale %d must be between %d and %d",
    1327              :                             tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
    1328          943 :         typmod = make_numeric_typmod(tl[0], tl[1]);
    1329              :     }
    1330           10 :     else if (n == 1)
    1331              :     {
    1332            4 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
    1333            0 :             ereport(ERROR,
    1334              :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1335              :                      errmsg("NUMERIC precision %d must be between 1 and %d",
    1336              :                             tl[0], NUMERIC_MAX_PRECISION)));
    1337              :         /* scale defaults to zero */
    1338            4 :         typmod = make_numeric_typmod(tl[0], 0);
    1339              :     }
    1340              :     else
    1341              :     {
    1342            6 :         ereport(ERROR,
    1343              :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1344              :                  errmsg("invalid NUMERIC type modifier")));
    1345              :         typmod = 0;             /* keep compiler quiet */
    1346              :     }
    1347              : 
    1348          947 :     PG_RETURN_INT32(typmod);
    1349              : }
    1350              : 
    1351              : Datum
    1352          188 : numerictypmodout(PG_FUNCTION_ARGS)
    1353              : {
    1354          188 :     int32       typmod = PG_GETARG_INT32(0);
    1355          188 :     char       *res = (char *) palloc(64);
    1356              : 
    1357          188 :     if (is_valid_numeric_typmod(typmod))
    1358          188 :         snprintf(res, 64, "(%d,%d)",
    1359              :                  numeric_typmod_precision(typmod),
    1360              :                  numeric_typmod_scale(typmod));
    1361              :     else
    1362            0 :         *res = '\0';
    1363              : 
    1364          188 :     PG_RETURN_CSTRING(res);
    1365              : }
    1366              : 
    1367              : 
    1368              : /* ----------------------------------------------------------------------
    1369              :  *
    1370              :  * Sign manipulation, rounding and the like
    1371              :  *
    1372              :  * ----------------------------------------------------------------------
    1373              :  */
    1374              : 
    1375              : Datum
    1376         9753 : numeric_abs(PG_FUNCTION_ARGS)
    1377              : {
    1378         9753 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1379              :     Numeric     res;
    1380              : 
    1381              :     /*
    1382              :      * Do it the easy way directly on the packed format
    1383              :      */
    1384         9753 :     res = duplicate_numeric(num);
    1385              : 
    1386         9753 :     if (NUMERIC_IS_SHORT(num))
    1387         9720 :         res->choice.n_short.n_header =
    1388         9720 :             num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
    1389           33 :     else if (NUMERIC_IS_SPECIAL(num))
    1390              :     {
    1391              :         /* This changes -Inf to Inf, and doesn't affect NaN */
    1392            9 :         res->choice.n_short.n_header =
    1393            9 :             num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
    1394              :     }
    1395              :     else
    1396           24 :         res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
    1397              : 
    1398         9753 :     PG_RETURN_NUMERIC(res);
    1399              : }
    1400              : 
    1401              : 
    1402              : Datum
    1403          442 : numeric_uminus(PG_FUNCTION_ARGS)
    1404              : {
    1405          442 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1406              :     Numeric     res;
    1407              : 
    1408              :     /*
    1409              :      * Do it the easy way directly on the packed format
    1410              :      */
    1411          442 :     res = duplicate_numeric(num);
    1412              : 
    1413          442 :     if (NUMERIC_IS_SPECIAL(num))
    1414              :     {
    1415              :         /* Flip the sign, if it's Inf or -Inf */
    1416           63 :         if (!NUMERIC_IS_NAN(num))
    1417           42 :             res->choice.n_short.n_header =
    1418           42 :                 num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
    1419              :     }
    1420              : 
    1421              :     /*
    1422              :      * The packed format is known to be totally zero digit trimmed always. So
    1423              :      * once we've eliminated specials, we can identify a zero by the fact that
    1424              :      * there are no digits at all. Do nothing to a zero.
    1425              :      */
    1426          379 :     else if (NUMERIC_NDIGITS(num) != 0)
    1427              :     {
    1428              :         /* Else, flip the sign */
    1429          322 :         if (NUMERIC_IS_SHORT(num))
    1430          322 :             res->choice.n_short.n_header =
    1431          322 :                 num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
    1432            0 :         else if (NUMERIC_SIGN(num) == NUMERIC_POS)
    1433            0 :             res->choice.n_long.n_sign_dscale =
    1434            0 :                 NUMERIC_NEG | NUMERIC_DSCALE(num);
    1435              :         else
    1436            0 :             res->choice.n_long.n_sign_dscale =
    1437            0 :                 NUMERIC_POS | NUMERIC_DSCALE(num);
    1438              :     }
    1439              : 
    1440          442 :     PG_RETURN_NUMERIC(res);
    1441              : }
    1442              : 
    1443              : 
    1444              : Datum
    1445            0 : numeric_uplus(PG_FUNCTION_ARGS)
    1446              : {
    1447            0 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1448              : 
    1449            0 :     PG_RETURN_NUMERIC(duplicate_numeric(num));
    1450              : }
    1451              : 
    1452              : 
    1453              : /*
    1454              :  * numeric_sign_internal() -
    1455              :  *
    1456              :  * Returns -1 if the argument is less than 0, 0 if the argument is equal
    1457              :  * to 0, and 1 if the argument is greater than zero.  Caller must have
    1458              :  * taken care of the NaN case, but we can handle infinities here.
    1459              :  */
    1460              : static int
    1461         1785 : numeric_sign_internal(Numeric num)
    1462              : {
    1463         1785 :     if (NUMERIC_IS_SPECIAL(num))
    1464              :     {
    1465              :         Assert(!NUMERIC_IS_NAN(num));
    1466              :         /* Must be Inf or -Inf */
    1467          156 :         if (NUMERIC_IS_PINF(num))
    1468           93 :             return 1;
    1469              :         else
    1470           63 :             return -1;
    1471              :     }
    1472              : 
    1473              :     /*
    1474              :      * The packed format is known to be totally zero digit trimmed always. So
    1475              :      * once we've eliminated specials, we can identify a zero by the fact that
    1476              :      * there are no digits at all.
    1477              :      */
    1478         1629 :     else if (NUMERIC_NDIGITS(num) == 0)
    1479          114 :         return 0;
    1480         1515 :     else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
    1481          366 :         return -1;
    1482              :     else
    1483         1149 :         return 1;
    1484              : }
    1485              : 
    1486              : /*
    1487              :  * numeric_sign() -
    1488              :  *
    1489              :  * returns -1 if the argument is less than 0, 0 if the argument is equal
    1490              :  * to 0, and 1 if the argument is greater than zero.
    1491              :  */
    1492              : Datum
    1493           24 : numeric_sign(PG_FUNCTION_ARGS)
    1494              : {
    1495           24 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1496              : 
    1497              :     /*
    1498              :      * Handle NaN (infinities can be handled normally)
    1499              :      */
    1500           24 :     if (NUMERIC_IS_NAN(num))
    1501            3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    1502              : 
    1503           21 :     switch (numeric_sign_internal(num))
    1504              :     {
    1505            3 :         case 0:
    1506            3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
    1507            9 :         case 1:
    1508            9 :             PG_RETURN_NUMERIC(make_result(&const_one));
    1509            9 :         case -1:
    1510            9 :             PG_RETURN_NUMERIC(make_result(&const_minus_one));
    1511              :     }
    1512              : 
    1513              :     Assert(false);
    1514            0 :     return (Datum) 0;
    1515              : }
    1516              : 
    1517              : 
    1518              : /*
    1519              :  * numeric_round() -
    1520              :  *
    1521              :  *  Round a value to have 'scale' digits after the decimal point.
    1522              :  *  We allow negative 'scale', implying rounding before the decimal
    1523              :  *  point --- Oracle interprets rounding that way.
    1524              :  */
    1525              : Datum
    1526         3904 : numeric_round(PG_FUNCTION_ARGS)
    1527              : {
    1528         3904 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1529         3904 :     int32       scale = PG_GETARG_INT32(1);
    1530              :     Numeric     res;
    1531              :     NumericVar  arg;
    1532              : 
    1533              :     /*
    1534              :      * Handle NaN and infinities
    1535              :      */
    1536         3904 :     if (NUMERIC_IS_SPECIAL(num))
    1537           48 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    1538              : 
    1539              :     /*
    1540              :      * Limit the scale value to avoid possible overflow in calculations.
    1541              :      *
    1542              :      * These limits are based on the maximum number of digits a Numeric value
    1543              :      * can have before and after the decimal point, but we must allow for one
    1544              :      * extra digit before the decimal point, in case the most significant
    1545              :      * digit rounds up; we must check if that causes Numeric overflow.
    1546              :      */
    1547         3856 :     scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
    1548         3856 :     scale = Min(scale, NUMERIC_DSCALE_MAX);
    1549              : 
    1550              :     /*
    1551              :      * Unpack the argument and round it at the proper digit position
    1552              :      */
    1553         3856 :     init_var(&arg);
    1554         3856 :     set_var_from_num(num, &arg);
    1555              : 
    1556         3856 :     round_var(&arg, scale);
    1557              : 
    1558              :     /* We don't allow negative output dscale */
    1559         3856 :     if (scale < 0)
    1560          108 :         arg.dscale = 0;
    1561              : 
    1562              :     /*
    1563              :      * Return the rounded result
    1564              :      */
    1565         3856 :     res = make_result(&arg);
    1566              : 
    1567         3853 :     free_var(&arg);
    1568         3853 :     PG_RETURN_NUMERIC(res);
    1569              : }
    1570              : 
    1571              : 
    1572              : /*
    1573              :  * numeric_trunc() -
    1574              :  *
    1575              :  *  Truncate a value to have 'scale' digits after the decimal point.
    1576              :  *  We allow negative 'scale', implying a truncation before the decimal
    1577              :  *  point --- Oracle interprets truncation that way.
    1578              :  */
    1579              : Datum
    1580          313 : numeric_trunc(PG_FUNCTION_ARGS)
    1581              : {
    1582          313 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1583          313 :     int32       scale = PG_GETARG_INT32(1);
    1584              :     Numeric     res;
    1585              :     NumericVar  arg;
    1586              : 
    1587              :     /*
    1588              :      * Handle NaN and infinities
    1589              :      */
    1590          313 :     if (NUMERIC_IS_SPECIAL(num))
    1591           18 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    1592              : 
    1593              :     /*
    1594              :      * Limit the scale value to avoid possible overflow in calculations.
    1595              :      *
    1596              :      * These limits are based on the maximum number of digits a Numeric value
    1597              :      * can have before and after the decimal point.
    1598              :      */
    1599          295 :     scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS);
    1600          295 :     scale = Min(scale, NUMERIC_DSCALE_MAX);
    1601              : 
    1602              :     /*
    1603              :      * Unpack the argument and truncate it at the proper digit position
    1604              :      */
    1605          295 :     init_var(&arg);
    1606          295 :     set_var_from_num(num, &arg);
    1607              : 
    1608          295 :     trunc_var(&arg, scale);
    1609              : 
    1610              :     /* We don't allow negative output dscale */
    1611          295 :     if (scale < 0)
    1612           12 :         arg.dscale = 0;
    1613              : 
    1614              :     /*
    1615              :      * Return the truncated result
    1616              :      */
    1617          295 :     res = make_result(&arg);
    1618              : 
    1619          295 :     free_var(&arg);
    1620          295 :     PG_RETURN_NUMERIC(res);
    1621              : }
    1622              : 
    1623              : 
    1624              : /*
    1625              :  * numeric_ceil() -
    1626              :  *
    1627              :  *  Return the smallest integer greater than or equal to the argument
    1628              :  */
    1629              : Datum
    1630          111 : numeric_ceil(PG_FUNCTION_ARGS)
    1631              : {
    1632          111 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1633              :     Numeric     res;
    1634              :     NumericVar  result;
    1635              : 
    1636              :     /*
    1637              :      * Handle NaN and infinities
    1638              :      */
    1639          111 :     if (NUMERIC_IS_SPECIAL(num))
    1640            9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    1641              : 
    1642          102 :     init_var_from_num(num, &result);
    1643          102 :     ceil_var(&result, &result);
    1644              : 
    1645          102 :     res = make_result(&result);
    1646          102 :     free_var(&result);
    1647              : 
    1648          102 :     PG_RETURN_NUMERIC(res);
    1649              : }
    1650              : 
    1651              : 
    1652              : /*
    1653              :  * numeric_floor() -
    1654              :  *
    1655              :  *  Return the largest integer equal to or less than the argument
    1656              :  */
    1657              : Datum
    1658           63 : numeric_floor(PG_FUNCTION_ARGS)
    1659              : {
    1660           63 :     Numeric     num = PG_GETARG_NUMERIC(0);
    1661              :     Numeric     res;
    1662              :     NumericVar  result;
    1663              : 
    1664              :     /*
    1665              :      * Handle NaN and infinities
    1666              :      */
    1667           63 :     if (NUMERIC_IS_SPECIAL(num))
    1668            9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    1669              : 
    1670           54 :     init_var_from_num(num, &result);
    1671           54 :     floor_var(&result, &result);
    1672              : 
    1673           54 :     res = make_result(&result);
    1674           54 :     free_var(&result);
    1675              : 
    1676           54 :     PG_RETURN_NUMERIC(res);
    1677              : }
    1678              : 
    1679              : 
    1680              : /*
    1681              :  * generate_series_numeric() -
    1682              :  *
    1683              :  *  Generate series of numeric.
    1684              :  */
    1685              : Datum
    1686        60192 : generate_series_numeric(PG_FUNCTION_ARGS)
    1687              : {
    1688        60192 :     return generate_series_step_numeric(fcinfo);
    1689              : }
    1690              : 
    1691              : Datum
    1692        60417 : generate_series_step_numeric(PG_FUNCTION_ARGS)
    1693              : {
    1694              :     generate_series_numeric_fctx *fctx;
    1695              :     FuncCallContext *funcctx;
    1696              :     MemoryContext oldcontext;
    1697              : 
    1698        60417 :     if (SRF_IS_FIRSTCALL())
    1699              :     {
    1700           87 :         Numeric     start_num = PG_GETARG_NUMERIC(0);
    1701           87 :         Numeric     stop_num = PG_GETARG_NUMERIC(1);
    1702           87 :         NumericVar  steploc = const_one;
    1703              : 
    1704              :         /* Reject NaN and infinities in start and stop values */
    1705           87 :         if (NUMERIC_IS_SPECIAL(start_num))
    1706              :         {
    1707            6 :             if (NUMERIC_IS_NAN(start_num))
    1708            3 :                 ereport(ERROR,
    1709              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1710              :                          errmsg("start value cannot be NaN")));
    1711              :             else
    1712            3 :                 ereport(ERROR,
    1713              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1714              :                          errmsg("start value cannot be infinity")));
    1715              :         }
    1716           81 :         if (NUMERIC_IS_SPECIAL(stop_num))
    1717              :         {
    1718            6 :             if (NUMERIC_IS_NAN(stop_num))
    1719            3 :                 ereport(ERROR,
    1720              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1721              :                          errmsg("stop value cannot be NaN")));
    1722              :             else
    1723            3 :                 ereport(ERROR,
    1724              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1725              :                          errmsg("stop value cannot be infinity")));
    1726              :         }
    1727              : 
    1728              :         /* see if we were given an explicit step size */
    1729           75 :         if (PG_NARGS() == 3)
    1730              :         {
    1731           36 :             Numeric     step_num = PG_GETARG_NUMERIC(2);
    1732              : 
    1733           36 :             if (NUMERIC_IS_SPECIAL(step_num))
    1734              :             {
    1735            6 :                 if (NUMERIC_IS_NAN(step_num))
    1736            3 :                     ereport(ERROR,
    1737              :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1738              :                              errmsg("step size cannot be NaN")));
    1739              :                 else
    1740            3 :                     ereport(ERROR,
    1741              :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1742              :                              errmsg("step size cannot be infinity")));
    1743              :             }
    1744              : 
    1745           30 :             init_var_from_num(step_num, &steploc);
    1746              : 
    1747           30 :             if (cmp_var(&steploc, &const_zero) == 0)
    1748            3 :                 ereport(ERROR,
    1749              :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1750              :                          errmsg("step size cannot equal zero")));
    1751              :         }
    1752              : 
    1753              :         /* create a function context for cross-call persistence */
    1754           66 :         funcctx = SRF_FIRSTCALL_INIT();
    1755              : 
    1756              :         /*
    1757              :          * Switch to memory context appropriate for multiple function calls.
    1758              :          */
    1759           66 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1760              : 
    1761              :         /* allocate memory for user context */
    1762           66 :         fctx = palloc_object(generate_series_numeric_fctx);
    1763              : 
    1764              :         /*
    1765              :          * Use fctx to keep state from call to call. Seed current with the
    1766              :          * original start value. We must copy the start_num and stop_num
    1767              :          * values rather than pointing to them, since we may have detoasted
    1768              :          * them in the per-call context.
    1769              :          */
    1770           66 :         init_var(&fctx->current);
    1771           66 :         init_var(&fctx->stop);
    1772           66 :         init_var(&fctx->step);
    1773              : 
    1774           66 :         set_var_from_num(start_num, &fctx->current);
    1775           66 :         set_var_from_num(stop_num, &fctx->stop);
    1776           66 :         set_var_from_var(&steploc, &fctx->step);
    1777              : 
    1778           66 :         funcctx->user_fctx = fctx;
    1779           66 :         MemoryContextSwitchTo(oldcontext);
    1780              :     }
    1781              : 
    1782              :     /* stuff done on every call of the function */
    1783        60396 :     funcctx = SRF_PERCALL_SETUP();
    1784              : 
    1785              :     /*
    1786              :      * Get the saved state and use current state as the result of this
    1787              :      * iteration.
    1788              :      */
    1789        60396 :     fctx = funcctx->user_fctx;
    1790              : 
    1791       120702 :     if ((fctx->step.sign == NUMERIC_POS &&
    1792        60306 :          cmp_var(&fctx->current, &fctx->stop) <= 0) ||
    1793          240 :         (fctx->step.sign == NUMERIC_NEG &&
    1794           90 :          cmp_var(&fctx->current, &fctx->stop) >= 0))
    1795              :     {
    1796        60330 :         Numeric     result = make_result(&fctx->current);
    1797              : 
    1798              :         /* switch to memory context appropriate for iteration calculation */
    1799        60330 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1800              : 
    1801              :         /* increment current in preparation for next iteration */
    1802        60330 :         add_var(&fctx->current, &fctx->step, &fctx->current);
    1803        60330 :         MemoryContextSwitchTo(oldcontext);
    1804              : 
    1805              :         /* do when there is more left to send */
    1806        60330 :         SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
    1807              :     }
    1808              :     else
    1809              :         /* do when there is no more left */
    1810           66 :         SRF_RETURN_DONE(funcctx);
    1811              : }
    1812              : 
    1813              : /*
    1814              :  * Planner support function for generate_series(numeric, numeric [, numeric])
    1815              :  */
    1816              : Datum
    1817          321 : generate_series_numeric_support(PG_FUNCTION_ARGS)
    1818              : {
    1819          321 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1820          321 :     Node       *ret = NULL;
    1821              : 
    1822          321 :     if (IsA(rawreq, SupportRequestRows))
    1823              :     {
    1824              :         /* Try to estimate the number of rows returned */
    1825           78 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
    1826              : 
    1827           78 :         if (is_funcclause(req->node))    /* be paranoid */
    1828              :         {
    1829           78 :             List       *args = ((FuncExpr *) req->node)->args;
    1830              :             Node       *arg1,
    1831              :                        *arg2,
    1832              :                        *arg3;
    1833              : 
    1834              :             /* We can use estimated argument values here */
    1835           78 :             arg1 = estimate_expression_value(req->root, linitial(args));
    1836           78 :             arg2 = estimate_expression_value(req->root, lsecond(args));
    1837           78 :             if (list_length(args) >= 3)
    1838           51 :                 arg3 = estimate_expression_value(req->root, lthird(args));
    1839              :             else
    1840           27 :                 arg3 = NULL;
    1841              : 
    1842              :             /*
    1843              :              * If any argument is constant NULL, we can safely assume that
    1844              :              * zero rows are returned.  Otherwise, if they're all non-NULL
    1845              :              * constants, we can calculate the number of rows that will be
    1846              :              * returned.
    1847              :              */
    1848           78 :             if ((IsA(arg1, Const) &&
    1849           75 :                  ((Const *) arg1)->constisnull) ||
    1850           78 :                 (IsA(arg2, Const) &&
    1851           78 :                  ((Const *) arg2)->constisnull) ||
    1852           51 :                 (arg3 != NULL && IsA(arg3, Const) &&
    1853           48 :                  ((Const *) arg3)->constisnull))
    1854              :             {
    1855            0 :                 req->rows = 0;
    1856            0 :                 ret = (Node *) req;
    1857              :             }
    1858           78 :             else if (IsA(arg1, Const) &&
    1859           75 :                      IsA(arg2, Const) &&
    1860           51 :                      (arg3 == NULL || IsA(arg3, Const)))
    1861              :             {
    1862              :                 Numeric     start_num;
    1863              :                 Numeric     stop_num;
    1864           69 :                 NumericVar  step = const_one;
    1865              : 
    1866              :                 /*
    1867              :                  * If any argument is NaN or infinity, generate_series() will
    1868              :                  * error out, so we needn't produce an estimate.
    1869              :                  */
    1870           69 :                 start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
    1871           69 :                 stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
    1872              : 
    1873           69 :                 if (NUMERIC_IS_SPECIAL(start_num) ||
    1874           60 :                     NUMERIC_IS_SPECIAL(stop_num))
    1875           24 :                     PG_RETURN_POINTER(NULL);
    1876              : 
    1877           54 :                 if (arg3)
    1878              :                 {
    1879              :                     Numeric     step_num;
    1880              : 
    1881           33 :                     step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
    1882              : 
    1883           33 :                     if (NUMERIC_IS_SPECIAL(step_num))
    1884            9 :                         PG_RETURN_POINTER(NULL);
    1885              : 
    1886           24 :                     init_var_from_num(step_num, &step);
    1887              :                 }
    1888              : 
    1889              :                 /*
    1890              :                  * The number of rows that will be returned is given by
    1891              :                  * floor((stop - start) / step) + 1, if the sign of step
    1892              :                  * matches the sign of stop - start.  Otherwise, no rows will
    1893              :                  * be returned.
    1894              :                  */
    1895           45 :                 if (cmp_var(&step, &const_zero) != 0)
    1896              :                 {
    1897              :                     NumericVar  start;
    1898              :                     NumericVar  stop;
    1899              :                     NumericVar  res;
    1900              : 
    1901           39 :                     init_var_from_num(start_num, &start);
    1902           39 :                     init_var_from_num(stop_num, &stop);
    1903              : 
    1904           39 :                     init_var(&res);
    1905           39 :                     sub_var(&stop, &start, &res);
    1906              : 
    1907           39 :                     if (step.sign != res.sign)
    1908              :                     {
    1909              :                         /* no rows will be returned */
    1910            3 :                         req->rows = 0;
    1911            3 :                         ret = (Node *) req;
    1912              :                     }
    1913              :                     else
    1914              :                     {
    1915           36 :                         if (arg3)
    1916           15 :                             div_var(&res, &step, &res, 0, false, false);
    1917              :                         else
    1918           21 :                             trunc_var(&res, 0); /* step = 1 */
    1919              : 
    1920           36 :                         req->rows = numericvar_to_double_no_overflow(&res) + 1;
    1921           36 :                         ret = (Node *) req;
    1922              :                     }
    1923              : 
    1924           39 :                     free_var(&res);
    1925              :                 }
    1926              :             }
    1927              :         }
    1928              :     }
    1929              : 
    1930          297 :     PG_RETURN_POINTER(ret);
    1931              : }
    1932              : 
    1933              : 
    1934              : /*
    1935              :  * Implements the numeric version of the width_bucket() function
    1936              :  * defined by SQL2003. See also width_bucket_float8().
    1937              :  *
    1938              :  * 'bound1' and 'bound2' are the lower and upper bounds of the
    1939              :  * histogram's range, respectively. 'count' is the number of buckets
    1940              :  * in the histogram. width_bucket() returns an integer indicating the
    1941              :  * bucket number that 'operand' belongs to in an equiwidth histogram
    1942              :  * with the specified characteristics. An operand smaller than the
    1943              :  * lower bound is assigned to bucket 0. An operand greater than or equal
    1944              :  * to the upper bound is assigned to an additional bucket (with number
    1945              :  * count+1). We don't allow the histogram bounds to be NaN or +/- infinity,
    1946              :  * but we do allow those values for the operand (taking NaN to be larger
    1947              :  * than any other value, as we do in comparisons).
    1948              :  */
    1949              : Datum
    1950          393 : width_bucket_numeric(PG_FUNCTION_ARGS)
    1951              : {
    1952          393 :     Numeric     operand = PG_GETARG_NUMERIC(0);
    1953          393 :     Numeric     bound1 = PG_GETARG_NUMERIC(1);
    1954          393 :     Numeric     bound2 = PG_GETARG_NUMERIC(2);
    1955          393 :     int32       count = PG_GETARG_INT32(3);
    1956              :     NumericVar  count_var;
    1957              :     NumericVar  result_var;
    1958              :     int32       result;
    1959              : 
    1960          393 :     if (count <= 0)
    1961            6 :         ereport(ERROR,
    1962              :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1963              :                  errmsg("count must be greater than zero")));
    1964              : 
    1965          387 :     if (NUMERIC_IS_SPECIAL(bound1) || NUMERIC_IS_SPECIAL(bound2))
    1966              :     {
    1967           12 :         if (NUMERIC_IS_NAN(bound1) || NUMERIC_IS_NAN(bound2))
    1968            3 :             ereport(ERROR,
    1969              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1970              :                      errmsg("lower and upper bounds cannot be NaN")));
    1971              : 
    1972            9 :         if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
    1973            9 :             ereport(ERROR,
    1974              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1975              :                      errmsg("lower and upper bounds must be finite")));
    1976              :     }
    1977              : 
    1978          375 :     init_var(&result_var);
    1979          375 :     init_var(&count_var);
    1980              : 
    1981              :     /* Convert 'count' to a numeric, for ease of use later */
    1982          375 :     int64_to_numericvar((int64) count, &count_var);
    1983              : 
    1984          375 :     switch (cmp_numerics(bound1, bound2))
    1985              :     {
    1986            3 :         case 0:
    1987            3 :             ereport(ERROR,
    1988              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
    1989              :                      errmsg("lower bound cannot equal upper bound")));
    1990              :             break;
    1991              : 
    1992              :             /* bound1 < bound2 */
    1993          276 :         case -1:
    1994          276 :             if (cmp_numerics(operand, bound1) < 0)
    1995           57 :                 set_var_from_var(&const_zero, &result_var);
    1996          219 :             else if (cmp_numerics(operand, bound2) >= 0)
    1997           57 :                 add_var(&count_var, &const_one, &result_var);
    1998              :             else
    1999          162 :                 compute_bucket(operand, bound1, bound2, &count_var,
    2000              :                                &result_var);
    2001          276 :             break;
    2002              : 
    2003              :             /* bound1 > bound2 */
    2004           96 :         case 1:
    2005           96 :             if (cmp_numerics(operand, bound1) > 0)
    2006            6 :                 set_var_from_var(&const_zero, &result_var);
    2007           90 :             else if (cmp_numerics(operand, bound2) <= 0)
    2008           12 :                 add_var(&count_var, &const_one, &result_var);
    2009              :             else
    2010           78 :                 compute_bucket(operand, bound1, bound2, &count_var,
    2011              :                                &result_var);
    2012           96 :             break;
    2013              :     }
    2014              : 
    2015              :     /* if result exceeds the range of a legal int4, we ereport here */
    2016          372 :     if (!numericvar_to_int32(&result_var, &result))
    2017            0 :         ereport(ERROR,
    2018              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2019              :                  errmsg("integer out of range")));
    2020              : 
    2021          372 :     free_var(&count_var);
    2022          372 :     free_var(&result_var);
    2023              : 
    2024          372 :     PG_RETURN_INT32(result);
    2025              : }
    2026              : 
    2027              : /*
    2028              :  * 'operand' is inside the bucket range, so determine the correct
    2029              :  * bucket for it to go in. The calculations performed by this function
    2030              :  * are derived directly from the SQL2003 spec. Note however that we
    2031              :  * multiply by count before dividing, to avoid unnecessary roundoff error.
    2032              :  */
    2033              : static void
    2034          240 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
    2035              :                const NumericVar *count_var, NumericVar *result_var)
    2036              : {
    2037              :     NumericVar  bound1_var;
    2038              :     NumericVar  bound2_var;
    2039              :     NumericVar  operand_var;
    2040              : 
    2041          240 :     init_var_from_num(bound1, &bound1_var);
    2042          240 :     init_var_from_num(bound2, &bound2_var);
    2043          240 :     init_var_from_num(operand, &operand_var);
    2044              : 
    2045              :     /*
    2046              :      * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
    2047              :      * bound1 <= operand < bound2 or bound1 >= operand > bound2.  Either way,
    2048              :      * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
    2049              :      * where the quotient is computed using floor division (i.e., division to
    2050              :      * zero decimal places with truncation), which guarantees that the result
    2051              :      * is in the range [1, count].  Reversing the bounds doesn't affect the
    2052              :      * computation, because the signs cancel out when dividing.
    2053              :      */
    2054          240 :     sub_var(&operand_var, &bound1_var, &operand_var);
    2055          240 :     sub_var(&bound2_var, &bound1_var, &bound2_var);
    2056              : 
    2057          240 :     mul_var(&operand_var, count_var, &operand_var,
    2058          240 :             operand_var.dscale + count_var->dscale);
    2059          240 :     div_var(&operand_var, &bound2_var, result_var, 0, false, true);
    2060          240 :     add_var(result_var, &const_one, result_var);
    2061              : 
    2062          240 :     free_var(&bound1_var);
    2063          240 :     free_var(&bound2_var);
    2064          240 :     free_var(&operand_var);
    2065          240 : }
    2066              : 
    2067              : /* ----------------------------------------------------------------------
    2068              :  *
    2069              :  * Comparison functions
    2070              :  *
    2071              :  * Note: btree indexes need these routines not to leak memory; therefore,
    2072              :  * be careful to free working copies of toasted datums.  Most places don't
    2073              :  * need to be so careful.
    2074              :  *
    2075              :  * Sort support:
    2076              :  *
    2077              :  * We implement the sortsupport strategy routine in order to get the benefit of
    2078              :  * abbreviation. The ordinary numeric comparison can be quite slow as a result
    2079              :  * of palloc/pfree cycles (due to detoasting packed values for alignment);
    2080              :  * while this could be worked on itself, the abbreviation strategy gives more
    2081              :  * speedup in many common cases.
    2082              :  *
    2083              :  * The abbreviated format is an int64. The representation is negated relative
    2084              :  * to the original value, because we use the largest negative value for NaN,
    2085              :  * which sorts higher than other values. We convert the absolute value of the
    2086              :  * numeric to a 63-bit positive value, and then negate it if the original
    2087              :  * number was positive.
    2088              :  *
    2089              :  * We abort the abbreviation process if the abbreviation cardinality is below
    2090              :  * 0.01% of the row count (1 per 10k non-null rows).  The actual break-even
    2091              :  * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
    2092              :  * very small penalty), but we don't want to build up too many abbreviated
    2093              :  * values before first testing for abort, so we take the slightly pessimistic
    2094              :  * number.  We make no attempt to estimate the cardinality of the real values,
    2095              :  * since it plays no part in the cost model here (if the abbreviation is equal,
    2096              :  * the cost of comparing equal and unequal underlying values is comparable).
    2097              :  * We discontinue even checking for abort (saving us the hashing overhead) if
    2098              :  * the estimated cardinality gets to 100k; that would be enough to support many
    2099              :  * billions of rows while doing no worse than breaking even.
    2100              :  *
    2101              :  * ----------------------------------------------------------------------
    2102              :  */
    2103              : 
    2104              : /*
    2105              :  * Sort support strategy routine.
    2106              :  */
    2107              : Datum
    2108          598 : numeric_sortsupport(PG_FUNCTION_ARGS)
    2109              : {
    2110          598 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
    2111              : 
    2112          598 :     ssup->comparator = numeric_fast_cmp;
    2113              : 
    2114          598 :     if (ssup->abbreviate)
    2115              :     {
    2116              :         NumericSortSupport *nss;
    2117          131 :         MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
    2118              : 
    2119          131 :         nss = palloc_object(NumericSortSupport);
    2120              : 
    2121              :         /*
    2122              :          * palloc a buffer for handling unaligned packed values in addition to
    2123              :          * the support struct
    2124              :          */
    2125          131 :         nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
    2126              : 
    2127          131 :         nss->input_count = 0;
    2128          131 :         nss->estimating = true;
    2129          131 :         initHyperLogLog(&nss->abbr_card, 10);
    2130              : 
    2131          131 :         ssup->ssup_extra = nss;
    2132              : 
    2133          131 :         ssup->abbrev_full_comparator = ssup->comparator;
    2134          131 :         ssup->comparator = numeric_cmp_abbrev;
    2135          131 :         ssup->abbrev_converter = numeric_abbrev_convert;
    2136          131 :         ssup->abbrev_abort = numeric_abbrev_abort;
    2137              : 
    2138          131 :         MemoryContextSwitchTo(oldcontext);
    2139              :     }
    2140              : 
    2141          598 :     PG_RETURN_VOID();
    2142              : }
    2143              : 
    2144              : /*
    2145              :  * Abbreviate a numeric datum, handling NaNs and detoasting
    2146              :  * (must not leak memory!)
    2147              :  */
    2148              : static Datum
    2149         9584 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
    2150              : {
    2151         9584 :     NumericSortSupport *nss = ssup->ssup_extra;
    2152         9584 :     void       *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
    2153              :     Numeric     value;
    2154              :     Datum       result;
    2155              : 
    2156         9584 :     nss->input_count += 1;
    2157              : 
    2158              :     /*
    2159              :      * This is to handle packed datums without needing a palloc/pfree cycle;
    2160              :      * we keep and reuse a buffer large enough to handle any short datum.
    2161              :      */
    2162         9584 :     if (VARATT_IS_SHORT(original_varatt))
    2163              :     {
    2164          513 :         void       *buf = nss->buf;
    2165          513 :         Size        sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
    2166              : 
    2167              :         Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
    2168              : 
    2169          513 :         SET_VARSIZE(buf, VARHDRSZ + sz);
    2170          513 :         memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
    2171              : 
    2172          513 :         value = (Numeric) buf;
    2173              :     }
    2174              :     else
    2175         9071 :         value = (Numeric) original_varatt;
    2176              : 
    2177         9584 :     if (NUMERIC_IS_SPECIAL(value))
    2178              :     {
    2179           75 :         if (NUMERIC_IS_PINF(value))
    2180           24 :             result = NUMERIC_ABBREV_PINF;
    2181           51 :         else if (NUMERIC_IS_NINF(value))
    2182           24 :             result = NUMERIC_ABBREV_NINF;
    2183              :         else
    2184           27 :             result = NUMERIC_ABBREV_NAN;
    2185              :     }
    2186              :     else
    2187              :     {
    2188              :         NumericVar  var;
    2189              : 
    2190         9509 :         init_var_from_num(value, &var);
    2191              : 
    2192         9509 :         result = numeric_abbrev_convert_var(&var, nss);
    2193              :     }
    2194              : 
    2195              :     /* should happen only for external/compressed toasts */
    2196         9584 :     if (original_varatt != DatumGetPointer(original_datum))
    2197            0 :         pfree(original_varatt);
    2198              : 
    2199         9584 :     return result;
    2200              : }
    2201              : 
    2202              : /*
    2203              :  * Consider whether to abort abbreviation.
    2204              :  *
    2205              :  * We pay no attention to the cardinality of the non-abbreviated data. There is
    2206              :  * no reason to do so: unlike text, we have no fast check for equal values, so
    2207              :  * we pay the full overhead whenever the abbreviations are equal regardless of
    2208              :  * whether the underlying values are also equal.
    2209              :  */
    2210              : static bool
    2211           72 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
    2212              : {
    2213           72 :     NumericSortSupport *nss = ssup->ssup_extra;
    2214              :     double      abbr_card;
    2215              : 
    2216           72 :     if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
    2217           72 :         return false;
    2218              : 
    2219            0 :     abbr_card = estimateHyperLogLog(&nss->abbr_card);
    2220              : 
    2221              :     /*
    2222              :      * If we have >100k distinct values, then even if we were sorting many
    2223              :      * billion rows we'd likely still break even, and the penalty of undoing
    2224              :      * that many rows of abbrevs would probably not be worth it. Stop even
    2225              :      * counting at that point.
    2226              :      */
    2227            0 :     if (abbr_card > 100000.0)
    2228              :     {
    2229            0 :         if (trace_sort)
    2230            0 :             elog(LOG,
    2231              :                  "numeric_abbrev: estimation ends at cardinality %f"
    2232              :                  " after " INT64_FORMAT " values (%d rows)",
    2233              :                  abbr_card, nss->input_count, memtupcount);
    2234            0 :         nss->estimating = false;
    2235            0 :         return false;
    2236              :     }
    2237              : 
    2238              :     /*
    2239              :      * Target minimum cardinality is 1 per ~10k of non-null inputs.  (The
    2240              :      * break even point is somewhere between one per 100k rows, where
    2241              :      * abbreviation has a very slight penalty, and 1 per 10k where it wins by
    2242              :      * a measurable percentage.)  We use the relatively pessimistic 10k
    2243              :      * threshold, and add a 0.5 row fudge factor, because it allows us to
    2244              :      * abort earlier on genuinely pathological data where we've had exactly
    2245              :      * one abbreviated value in the first 10k (non-null) rows.
    2246              :      */
    2247            0 :     if (abbr_card < nss->input_count / 10000.0 + 0.5)
    2248              :     {
    2249            0 :         if (trace_sort)
    2250            0 :             elog(LOG,
    2251              :                  "numeric_abbrev: aborting abbreviation at cardinality %f"
    2252              :                  " below threshold %f after " INT64_FORMAT " values (%d rows)",
    2253              :                  abbr_card, nss->input_count / 10000.0 + 0.5,
    2254              :                  nss->input_count, memtupcount);
    2255            0 :         return true;
    2256              :     }
    2257              : 
    2258            0 :     if (trace_sort)
    2259            0 :         elog(LOG,
    2260              :              "numeric_abbrev: cardinality %f"
    2261              :              " after " INT64_FORMAT " values (%d rows)",
    2262              :              abbr_card, nss->input_count, memtupcount);
    2263              : 
    2264            0 :     return false;
    2265              : }
    2266              : 
    2267              : /*
    2268              :  * Non-fmgr interface to the comparison routine to allow sortsupport to elide
    2269              :  * the fmgr call.  The saving here is small given how slow numeric comparisons
    2270              :  * are, but it is a required part of the sort support API when abbreviations
    2271              :  * are performed.
    2272              :  *
    2273              :  * Two palloc/pfree cycles could be saved here by using persistent buffers for
    2274              :  * aligning short-varlena inputs, but this has not so far been considered to
    2275              :  * be worth the effort.
    2276              :  */
    2277              : static int
    2278     12907112 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
    2279              : {
    2280     12907112 :     Numeric     nx = DatumGetNumeric(x);
    2281     12907112 :     Numeric     ny = DatumGetNumeric(y);
    2282              :     int         result;
    2283              : 
    2284     12907112 :     result = cmp_numerics(nx, ny);
    2285              : 
    2286     12907112 :     if (nx != DatumGetPointer(x))
    2287      5557392 :         pfree(nx);
    2288     12907112 :     if (ny != DatumGetPointer(y))
    2289      5557389 :         pfree(ny);
    2290              : 
    2291     12907112 :     return result;
    2292              : }
    2293              : 
    2294              : /*
    2295              :  * Compare abbreviations of values. (Abbreviations may be equal where the true
    2296              :  * values differ, but if the abbreviations differ, they must reflect the
    2297              :  * ordering of the true values.)
    2298              :  */
    2299              : static int
    2300        96113 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
    2301              : {
    2302              :     /*
    2303              :      * NOTE WELL: this is intentionally backwards, because the abbreviation is
    2304              :      * negated relative to the original value, to handle NaN/infinity cases.
    2305              :      */
    2306        96113 :     if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
    2307        48798 :         return 1;
    2308        47315 :     if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
    2309        47206 :         return -1;
    2310          109 :     return 0;
    2311              : }
    2312              : 
    2313              : /*
    2314              :  * Abbreviate a NumericVar into the 64-bit sortsupport size.
    2315              :  *
    2316              :  * The 31-bit value is constructed as:
    2317              :  *
    2318              :  *  0 + 7bits digit weight + 24 bits digit value
    2319              :  *
    2320              :  * where the digit weight is in single decimal digits, not digit words, and
    2321              :  * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
    2322              :  * significant decimal digits of the value converted to binary. Values whose
    2323              :  * weights would fall outside the representable range are rounded off to zero
    2324              :  * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
    2325              :  * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
    2326              :  * where values are outside the range 10^-44 to 10^83, which is not considered
    2327              :  * to be a serious limitation, or when values are of the same magnitude and
    2328              :  * equal in the first 7 decimal digits, which is considered to be an
    2329              :  * unavoidable limitation given the available bits. (Stealing three more bits
    2330              :  * to compare another digit would narrow the range of representable weights by
    2331              :  * a factor of 8, which starts to look like a real limiting factor.)
    2332              :  *
    2333              :  * (The value 44 for the excess is essentially arbitrary)
    2334              :  *
    2335              :  * The 63-bit value is constructed as:
    2336              :  *
    2337              :  *  0 + 7bits weight + 4 x 14-bit packed digit words
    2338              :  *
    2339              :  * The weight in this case is again stored in excess-44, but this time it is
    2340              :  * the original weight in digit words (i.e. powers of 10000). The first four
    2341              :  * digit words of the value (if present; trailing zeros are assumed as needed)
    2342              :  * are packed into 14 bits each to form the rest of the value. Again,
    2343              :  * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
    2344              :  * representable range in this case is 10^-176 to 10^332, which is considered
    2345              :  * to be good enough for all practical purposes, and comparison of 4 words
    2346              :  * means that at least 13 decimal digits are compared, which is considered to
    2347              :  * be a reasonable compromise between effectiveness and efficiency in computing
    2348              :  * the abbreviation.
    2349              :  *
    2350              :  * (The value 44 for the excess is even more arbitrary here, it was chosen just
    2351              :  * to match the value used in the 31-bit case)
    2352              :  *
    2353              :  * [1] - Excess-k representation means that the value is offset by adding 'k'
    2354              :  * and then treated as unsigned, so the smallest representable value is stored
    2355              :  * with all bits zero. This allows simple comparisons to work on the composite
    2356              :  * value.
    2357              :  */
    2358              : static Datum
    2359         9509 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
    2360              : {
    2361         9509 :     int         ndigits = var->ndigits;
    2362         9509 :     int         weight = var->weight;
    2363              :     int64       result;
    2364              : 
    2365         9509 :     if (ndigits == 0 || weight < -44)
    2366              :     {
    2367           26 :         result = 0;
    2368              :     }
    2369         9483 :     else if (weight > 83)
    2370              :     {
    2371            6 :         result = PG_INT64_MAX;
    2372              :     }
    2373              :     else
    2374              :     {
    2375         9477 :         result = ((int64) (weight + 44) << 56);
    2376              : 
    2377         9477 :         switch (ndigits)
    2378              :         {
    2379            0 :             default:
    2380            0 :                 result |= ((int64) var->digits[3]);
    2381              :                 pg_fallthrough;
    2382         3102 :             case 3:
    2383         3102 :                 result |= ((int64) var->digits[2]) << 14;
    2384              :                 pg_fallthrough;
    2385         9148 :             case 2:
    2386         9148 :                 result |= ((int64) var->digits[1]) << 28;
    2387              :                 pg_fallthrough;
    2388         9477 :             case 1:
    2389         9477 :                 result |= ((int64) var->digits[0]) << 42;
    2390         9477 :                 break;
    2391              :         }
    2392              :     }
    2393              : 
    2394              :     /* the abbrev is negated relative to the original */
    2395         9509 :     if (var->sign == NUMERIC_POS)
    2396         9460 :         result = -result;
    2397              : 
    2398         9509 :     if (nss->estimating)
    2399              :     {
    2400         9509 :         uint32      tmp = ((uint32) result
    2401         9509 :                            ^ (uint32) ((uint64) result >> 32));
    2402              : 
    2403         9509 :         addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
    2404              :     }
    2405              : 
    2406         9509 :     return NumericAbbrevGetDatum(result);
    2407              : }
    2408              : 
    2409              : 
    2410              : /*
    2411              :  * Ordinary (non-sortsupport) comparisons follow.
    2412              :  */
    2413              : 
    2414              : Datum
    2415       380061 : numeric_cmp(PG_FUNCTION_ARGS)
    2416              : {
    2417       380061 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2418       380061 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2419              :     int         result;
    2420              : 
    2421       380061 :     result = cmp_numerics(num1, num2);
    2422              : 
    2423       380061 :     PG_FREE_IF_COPY(num1, 0);
    2424       380061 :     PG_FREE_IF_COPY(num2, 1);
    2425              : 
    2426       380061 :     PG_RETURN_INT32(result);
    2427              : }
    2428              : 
    2429              : 
    2430              : Datum
    2431       325275 : numeric_eq(PG_FUNCTION_ARGS)
    2432              : {
    2433       325275 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2434       325275 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2435              :     bool        result;
    2436              : 
    2437       325275 :     result = cmp_numerics(num1, num2) == 0;
    2438              : 
    2439       325275 :     PG_FREE_IF_COPY(num1, 0);
    2440       325275 :     PG_FREE_IF_COPY(num2, 1);
    2441              : 
    2442       325275 :     PG_RETURN_BOOL(result);
    2443              : }
    2444              : 
    2445              : Datum
    2446         2688 : numeric_ne(PG_FUNCTION_ARGS)
    2447              : {
    2448         2688 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2449         2688 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2450              :     bool        result;
    2451              : 
    2452         2688 :     result = cmp_numerics(num1, num2) != 0;
    2453              : 
    2454         2688 :     PG_FREE_IF_COPY(num1, 0);
    2455         2688 :     PG_FREE_IF_COPY(num2, 1);
    2456              : 
    2457         2688 :     PG_RETURN_BOOL(result);
    2458              : }
    2459              : 
    2460              : Datum
    2461        27859 : numeric_gt(PG_FUNCTION_ARGS)
    2462              : {
    2463        27859 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2464        27859 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2465              :     bool        result;
    2466              : 
    2467        27859 :     result = cmp_numerics(num1, num2) > 0;
    2468              : 
    2469        27859 :     PG_FREE_IF_COPY(num1, 0);
    2470        27859 :     PG_FREE_IF_COPY(num2, 1);
    2471              : 
    2472        27859 :     PG_RETURN_BOOL(result);
    2473              : }
    2474              : 
    2475              : Datum
    2476         7506 : numeric_ge(PG_FUNCTION_ARGS)
    2477              : {
    2478         7506 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2479         7506 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2480              :     bool        result;
    2481              : 
    2482         7506 :     result = cmp_numerics(num1, num2) >= 0;
    2483              : 
    2484         7506 :     PG_FREE_IF_COPY(num1, 0);
    2485         7506 :     PG_FREE_IF_COPY(num2, 1);
    2486              : 
    2487         7506 :     PG_RETURN_BOOL(result);
    2488              : }
    2489              : 
    2490              : Datum
    2491       149634 : numeric_lt(PG_FUNCTION_ARGS)
    2492              : {
    2493       149634 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2494       149634 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2495              :     bool        result;
    2496              : 
    2497       149634 :     result = cmp_numerics(num1, num2) < 0;
    2498              : 
    2499       149634 :     PG_FREE_IF_COPY(num1, 0);
    2500       149634 :     PG_FREE_IF_COPY(num2, 1);
    2501              : 
    2502       149634 :     PG_RETURN_BOOL(result);
    2503              : }
    2504              : 
    2505              : Datum
    2506         8444 : numeric_le(PG_FUNCTION_ARGS)
    2507              : {
    2508         8444 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2509         8444 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2510              :     bool        result;
    2511              : 
    2512         8444 :     result = cmp_numerics(num1, num2) <= 0;
    2513              : 
    2514         8444 :     PG_FREE_IF_COPY(num1, 0);
    2515         8444 :     PG_FREE_IF_COPY(num2, 1);
    2516              : 
    2517         8444 :     PG_RETURN_BOOL(result);
    2518              : }
    2519              : 
    2520              : static int
    2521     13819355 : cmp_numerics(Numeric num1, Numeric num2)
    2522              : {
    2523              :     int         result;
    2524              : 
    2525              :     /*
    2526              :      * We consider all NANs to be equal and larger than any non-NAN (including
    2527              :      * Infinity).  This is somewhat arbitrary; the important thing is to have
    2528              :      * a consistent sort order.
    2529              :      */
    2530     13819355 :     if (NUMERIC_IS_SPECIAL(num1))
    2531              :     {
    2532         3118 :         if (NUMERIC_IS_NAN(num1))
    2533              :         {
    2534         3073 :             if (NUMERIC_IS_NAN(num2))
    2535          374 :                 result = 0;     /* NAN = NAN */
    2536              :             else
    2537         2699 :                 result = 1;     /* NAN > non-NAN */
    2538              :         }
    2539           45 :         else if (NUMERIC_IS_PINF(num1))
    2540              :         {
    2541           36 :             if (NUMERIC_IS_NAN(num2))
    2542            0 :                 result = -1;    /* PINF < NAN */
    2543           36 :             else if (NUMERIC_IS_PINF(num2))
    2544            3 :                 result = 0;     /* PINF = PINF */
    2545              :             else
    2546           33 :                 result = 1;     /* PINF > anything else */
    2547              :         }
    2548              :         else                    /* num1 must be NINF */
    2549              :         {
    2550            9 :             if (NUMERIC_IS_NINF(num2))
    2551            3 :                 result = 0;     /* NINF = NINF */
    2552              :             else
    2553            6 :                 result = -1;    /* NINF < anything else */
    2554              :         }
    2555              :     }
    2556     13816237 :     else if (NUMERIC_IS_SPECIAL(num2))
    2557              :     {
    2558         5578 :         if (NUMERIC_IS_NINF(num2))
    2559            6 :             result = 1;         /* normal > NINF */
    2560              :         else
    2561         5572 :             result = -1;        /* normal < NAN or PINF */
    2562              :     }
    2563              :     else
    2564              :     {
    2565     27621832 :         result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
    2566     13810810 :                                 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
    2567     13810659 :                                 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
    2568     13811022 :                                 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
    2569              :     }
    2570              : 
    2571     13819355 :     return result;
    2572              : }
    2573              : 
    2574              : /*
    2575              :  * in_range support function for numeric.
    2576              :  */
    2577              : Datum
    2578          576 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
    2579              : {
    2580          576 :     Numeric     val = PG_GETARG_NUMERIC(0);
    2581          576 :     Numeric     base = PG_GETARG_NUMERIC(1);
    2582          576 :     Numeric     offset = PG_GETARG_NUMERIC(2);
    2583          576 :     bool        sub = PG_GETARG_BOOL(3);
    2584          576 :     bool        less = PG_GETARG_BOOL(4);
    2585              :     bool        result;
    2586              : 
    2587              :     /*
    2588              :      * Reject negative (including -Inf) or NaN offset.  Negative is per spec,
    2589              :      * and NaN is because appropriate semantics for that seem non-obvious.
    2590              :      */
    2591          576 :     if (NUMERIC_IS_NAN(offset) ||
    2592          573 :         NUMERIC_IS_NINF(offset) ||
    2593          573 :         NUMERIC_SIGN(offset) == NUMERIC_NEG)
    2594            3 :         ereport(ERROR,
    2595              :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
    2596              :                  errmsg("invalid preceding or following size in window function")));
    2597              : 
    2598              :     /*
    2599              :      * Deal with cases where val and/or base is NaN, following the rule that
    2600              :      * NaN sorts after non-NaN (cf cmp_numerics).  The offset cannot affect
    2601              :      * the conclusion.
    2602              :      */
    2603          573 :     if (NUMERIC_IS_NAN(val))
    2604              :     {
    2605           93 :         if (NUMERIC_IS_NAN(base))
    2606           30 :             result = true;      /* NAN = NAN */
    2607              :         else
    2608           63 :             result = !less;     /* NAN > non-NAN */
    2609              :     }
    2610          480 :     else if (NUMERIC_IS_NAN(base))
    2611              :     {
    2612           63 :         result = less;          /* non-NAN < NAN */
    2613              :     }
    2614              : 
    2615              :     /*
    2616              :      * Deal with infinite offset (necessarily +Inf, at this point).
    2617              :      */
    2618          417 :     else if (NUMERIC_IS_SPECIAL(offset))
    2619              :     {
    2620              :         Assert(NUMERIC_IS_PINF(offset));
    2621          210 :         if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
    2622              :         {
    2623              :             /*
    2624              :              * base +/- offset would produce NaN, so return true for any val
    2625              :              * (see in_range_float8_float8() for reasoning).
    2626              :              */
    2627           87 :             result = true;
    2628              :         }
    2629          123 :         else if (sub)
    2630              :         {
    2631              :             /* base - offset must be -inf */
    2632           75 :             if (less)
    2633           27 :                 result = NUMERIC_IS_NINF(val);  /* only -inf is <= sum */
    2634              :             else
    2635           48 :                 result = true;  /* any val is >= sum */
    2636              :         }
    2637              :         else
    2638              :         {
    2639              :             /* base + offset must be +inf */
    2640           48 :             if (less)
    2641            0 :                 result = true;  /* any val is <= sum */
    2642              :             else
    2643           48 :                 result = NUMERIC_IS_PINF(val);  /* only +inf is >= sum */
    2644              :         }
    2645              :     }
    2646              : 
    2647              :     /*
    2648              :      * Deal with cases where val and/or base is infinite.  The offset, being
    2649              :      * now known finite, cannot affect the conclusion.
    2650              :      */
    2651          207 :     else if (NUMERIC_IS_SPECIAL(val))
    2652              :     {
    2653           39 :         if (NUMERIC_IS_PINF(val))
    2654              :         {
    2655           18 :             if (NUMERIC_IS_PINF(base))
    2656           12 :                 result = true;  /* PINF = PINF */
    2657              :             else
    2658            6 :                 result = !less; /* PINF > any other non-NAN */
    2659              :         }
    2660              :         else                    /* val must be NINF */
    2661              :         {
    2662           21 :             if (NUMERIC_IS_NINF(base))
    2663           15 :                 result = true;  /* NINF = NINF */
    2664              :             else
    2665            6 :                 result = less;  /* NINF < anything else */
    2666              :         }
    2667              :     }
    2668          168 :     else if (NUMERIC_IS_SPECIAL(base))
    2669              :     {
    2670           12 :         if (NUMERIC_IS_NINF(base))
    2671            6 :             result = !less;     /* normal > NINF */
    2672              :         else
    2673            6 :             result = less;      /* normal < PINF */
    2674              :     }
    2675              :     else
    2676              :     {
    2677              :         /*
    2678              :          * Otherwise go ahead and compute base +/- offset.  While it's
    2679              :          * possible for this to overflow the numeric format, it's unlikely
    2680              :          * enough that we don't take measures to prevent it.
    2681              :          */
    2682              :         NumericVar  valv;
    2683              :         NumericVar  basev;
    2684              :         NumericVar  offsetv;
    2685              :         NumericVar  sum;
    2686              : 
    2687          156 :         init_var_from_num(val, &valv);
    2688          156 :         init_var_from_num(base, &basev);
    2689          156 :         init_var_from_num(offset, &offsetv);
    2690          156 :         init_var(&sum);
    2691              : 
    2692          156 :         if (sub)
    2693           78 :             sub_var(&basev, &offsetv, &sum);
    2694              :         else
    2695           78 :             add_var(&basev, &offsetv, &sum);
    2696              : 
    2697          156 :         if (less)
    2698           78 :             result = (cmp_var(&valv, &sum) <= 0);
    2699              :         else
    2700           78 :             result = (cmp_var(&valv, &sum) >= 0);
    2701              : 
    2702          156 :         free_var(&sum);
    2703              :     }
    2704              : 
    2705          573 :     PG_FREE_IF_COPY(val, 0);
    2706          573 :     PG_FREE_IF_COPY(base, 1);
    2707          573 :     PG_FREE_IF_COPY(offset, 2);
    2708              : 
    2709          573 :     PG_RETURN_BOOL(result);
    2710              : }
    2711              : 
    2712              : Datum
    2713       303768 : hash_numeric(PG_FUNCTION_ARGS)
    2714              : {
    2715       303768 :     Numeric     key = PG_GETARG_NUMERIC(0);
    2716              :     Datum       digit_hash;
    2717              :     Datum       result;
    2718              :     int         weight;
    2719              :     int         start_offset;
    2720              :     int         end_offset;
    2721              :     int         i;
    2722              :     int         hash_len;
    2723              :     NumericDigit *digits;
    2724              : 
    2725              :     /* If it's NaN or infinity, don't try to hash the rest of the fields */
    2726       303768 :     if (NUMERIC_IS_SPECIAL(key))
    2727            0 :         PG_RETURN_UINT32(0);
    2728              : 
    2729       303768 :     weight = NUMERIC_WEIGHT(key);
    2730       303768 :     start_offset = 0;
    2731       303768 :     end_offset = 0;
    2732              : 
    2733              :     /*
    2734              :      * Omit any leading or trailing zeros from the input to the hash. The
    2735              :      * numeric implementation *should* guarantee that leading and trailing
    2736              :      * zeros are suppressed, but we're paranoid. Note that we measure the
    2737              :      * starting and ending offsets in units of NumericDigits, not bytes.
    2738              :      */
    2739       303768 :     digits = NUMERIC_DIGITS(key);
    2740       303768 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
    2741              :     {
    2742       302950 :         if (digits[i] != (NumericDigit) 0)
    2743       302950 :             break;
    2744              : 
    2745            0 :         start_offset++;
    2746              : 
    2747              :         /*
    2748              :          * The weight is effectively the # of digits before the decimal point,
    2749              :          * so decrement it for each leading zero we skip.
    2750              :          */
    2751            0 :         weight--;
    2752              :     }
    2753              : 
    2754              :     /*
    2755              :      * If there are no non-zero digits, then the value of the number is zero,
    2756              :      * regardless of any other fields.
    2757              :      */
    2758       303768 :     if (NUMERIC_NDIGITS(key) == start_offset)
    2759          818 :         PG_RETURN_UINT32(-1);
    2760              : 
    2761       302950 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
    2762              :     {
    2763       302950 :         if (digits[i] != (NumericDigit) 0)
    2764       302950 :             break;
    2765              : 
    2766            0 :         end_offset++;
    2767              :     }
    2768              : 
    2769              :     /* If we get here, there should be at least one non-zero digit */
    2770              :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
    2771              : 
    2772              :     /*
    2773              :      * Note that we don't hash on the Numeric's scale, since two numerics can
    2774              :      * compare equal but have different scales. We also don't hash on the
    2775              :      * sign, although we could: since a sign difference implies inequality,
    2776              :      * this shouldn't affect correctness.
    2777              :      */
    2778       302950 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
    2779       302950 :     digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
    2780              :                           hash_len * sizeof(NumericDigit));
    2781              : 
    2782              :     /* Mix in the weight, via XOR */
    2783       302950 :     result = digit_hash ^ weight;
    2784              : 
    2785       302950 :     PG_RETURN_DATUM(result);
    2786              : }
    2787              : 
    2788              : /*
    2789              :  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
    2790              :  * Otherwise, similar to hash_numeric.
    2791              :  */
    2792              : Datum
    2793           42 : hash_numeric_extended(PG_FUNCTION_ARGS)
    2794              : {
    2795           42 :     Numeric     key = PG_GETARG_NUMERIC(0);
    2796           42 :     uint64      seed = PG_GETARG_INT64(1);
    2797              :     Datum       digit_hash;
    2798              :     Datum       result;
    2799              :     int         weight;
    2800              :     int         start_offset;
    2801              :     int         end_offset;
    2802              :     int         i;
    2803              :     int         hash_len;
    2804              :     NumericDigit *digits;
    2805              : 
    2806              :     /* If it's NaN or infinity, don't try to hash the rest of the fields */
    2807           42 :     if (NUMERIC_IS_SPECIAL(key))
    2808            0 :         PG_RETURN_UINT64(seed);
    2809              : 
    2810           42 :     weight = NUMERIC_WEIGHT(key);
    2811           42 :     start_offset = 0;
    2812           42 :     end_offset = 0;
    2813              : 
    2814           42 :     digits = NUMERIC_DIGITS(key);
    2815           42 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
    2816              :     {
    2817           36 :         if (digits[i] != (NumericDigit) 0)
    2818           36 :             break;
    2819              : 
    2820            0 :         start_offset++;
    2821              : 
    2822            0 :         weight--;
    2823              :     }
    2824              : 
    2825           42 :     if (NUMERIC_NDIGITS(key) == start_offset)
    2826            6 :         PG_RETURN_UINT64(seed - 1);
    2827              : 
    2828           36 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
    2829              :     {
    2830           36 :         if (digits[i] != (NumericDigit) 0)
    2831           36 :             break;
    2832              : 
    2833            0 :         end_offset++;
    2834              :     }
    2835              : 
    2836              :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
    2837              : 
    2838           36 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
    2839           36 :     digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
    2840           36 :                                                       + start_offset),
    2841              :                                    hash_len * sizeof(NumericDigit),
    2842              :                                    seed);
    2843              : 
    2844           36 :     result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
    2845              : 
    2846           36 :     PG_RETURN_DATUM(result);
    2847              : }
    2848              : 
    2849              : 
    2850              : /* ----------------------------------------------------------------------
    2851              :  *
    2852              :  * Basic arithmetic functions
    2853              :  *
    2854              :  * ----------------------------------------------------------------------
    2855              :  */
    2856              : 
    2857              : 
    2858              : /*
    2859              :  * numeric_add() -
    2860              :  *
    2861              :  *  Add two numerics
    2862              :  */
    2863              : Datum
    2864       126321 : numeric_add(PG_FUNCTION_ARGS)
    2865              : {
    2866       126321 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2867       126321 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2868              :     Numeric     res;
    2869              : 
    2870       126321 :     res = numeric_add_safe(num1, num2, NULL);
    2871              : 
    2872       126321 :     PG_RETURN_NUMERIC(res);
    2873              : }
    2874              : 
    2875              : /*
    2876              :  * numeric_add_safe() -
    2877              :  *
    2878              :  *  Internal version of numeric_add() with support for soft error reporting.
    2879              :  */
    2880              : Numeric
    2881       126840 : numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
    2882              : {
    2883              :     NumericVar  arg1;
    2884              :     NumericVar  arg2;
    2885              :     NumericVar  result;
    2886              :     Numeric     res;
    2887              : 
    2888              :     /*
    2889              :      * Handle NaN and infinities
    2890              :      */
    2891       126840 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    2892              :     {
    2893           99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2894           39 :             return make_result(&const_nan);
    2895           60 :         if (NUMERIC_IS_PINF(num1))
    2896              :         {
    2897           18 :             if (NUMERIC_IS_NINF(num2))
    2898            3 :                 return make_result(&const_nan); /* Inf + -Inf */
    2899              :             else
    2900           15 :                 return make_result(&const_pinf);
    2901              :         }
    2902           42 :         if (NUMERIC_IS_NINF(num1))
    2903              :         {
    2904           18 :             if (NUMERIC_IS_PINF(num2))
    2905            3 :                 return make_result(&const_nan); /* -Inf + Inf */
    2906              :             else
    2907           15 :                 return make_result(&const_ninf);
    2908              :         }
    2909              :         /* by here, num1 must be finite, so num2 is not */
    2910           24 :         if (NUMERIC_IS_PINF(num2))
    2911           12 :             return make_result(&const_pinf);
    2912              :         Assert(NUMERIC_IS_NINF(num2));
    2913           12 :         return make_result(&const_ninf);
    2914              :     }
    2915              : 
    2916              :     /*
    2917              :      * Unpack the values, let add_var() compute the result and return it.
    2918              :      */
    2919       126741 :     init_var_from_num(num1, &arg1);
    2920       126741 :     init_var_from_num(num2, &arg2);
    2921              : 
    2922       126741 :     init_var(&result);
    2923       126741 :     add_var(&arg1, &arg2, &result);
    2924              : 
    2925       126741 :     res = make_result_safe(&result, escontext);
    2926              : 
    2927       126741 :     free_var(&result);
    2928              : 
    2929       126741 :     return res;
    2930              : }
    2931              : 
    2932              : 
    2933              : /*
    2934              :  * numeric_sub() -
    2935              :  *
    2936              :  *  Subtract one numeric from another
    2937              :  */
    2938              : Datum
    2939        37833 : numeric_sub(PG_FUNCTION_ARGS)
    2940              : {
    2941        37833 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    2942        37833 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    2943              :     Numeric     res;
    2944              : 
    2945        37833 :     res = numeric_sub_safe(num1, num2, NULL);
    2946              : 
    2947        37833 :     PG_RETURN_NUMERIC(res);
    2948              : }
    2949              : 
    2950              : 
    2951              : /*
    2952              :  * numeric_sub_safe() -
    2953              :  *
    2954              :  *  Internal version of numeric_sub() with support for soft error reporting.
    2955              :  */
    2956              : Numeric
    2957        37908 : numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
    2958              : {
    2959              :     NumericVar  arg1;
    2960              :     NumericVar  arg2;
    2961              :     NumericVar  result;
    2962              :     Numeric     res;
    2963              : 
    2964              :     /*
    2965              :      * Handle NaN and infinities
    2966              :      */
    2967        37908 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    2968              :     {
    2969           99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    2970           39 :             return make_result(&const_nan);
    2971           60 :         if (NUMERIC_IS_PINF(num1))
    2972              :         {
    2973           18 :             if (NUMERIC_IS_PINF(num2))
    2974            3 :                 return make_result(&const_nan); /* Inf - Inf */
    2975              :             else
    2976           15 :                 return make_result(&const_pinf);
    2977              :         }
    2978           42 :         if (NUMERIC_IS_NINF(num1))
    2979              :         {
    2980           18 :             if (NUMERIC_IS_NINF(num2))
    2981            3 :                 return make_result(&const_nan); /* -Inf - -Inf */
    2982              :             else
    2983           15 :                 return make_result(&const_ninf);
    2984              :         }
    2985              :         /* by here, num1 must be finite, so num2 is not */
    2986           24 :         if (NUMERIC_IS_PINF(num2))
    2987           12 :             return make_result(&const_ninf);
    2988              :         Assert(NUMERIC_IS_NINF(num2));
    2989           12 :         return make_result(&const_pinf);
    2990              :     }
    2991              : 
    2992              :     /*
    2993              :      * Unpack the values, let sub_var() compute the result and return it.
    2994              :      */
    2995        37809 :     init_var_from_num(num1, &arg1);
    2996        37809 :     init_var_from_num(num2, &arg2);
    2997              : 
    2998        37809 :     init_var(&result);
    2999        37809 :     sub_var(&arg1, &arg2, &result);
    3000              : 
    3001        37809 :     res = make_result_safe(&result, escontext);
    3002              : 
    3003        37809 :     free_var(&result);
    3004              : 
    3005        37809 :     return res;
    3006              : }
    3007              : 
    3008              : 
    3009              : /*
    3010              :  * numeric_mul() -
    3011              :  *
    3012              :  *  Calculate the product of two numerics
    3013              :  */
    3014              : Datum
    3015       245100 : numeric_mul(PG_FUNCTION_ARGS)
    3016              : {
    3017       245100 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3018       245100 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3019              :     Numeric     res;
    3020              : 
    3021       245100 :     res = numeric_mul_safe(num1, num2, NULL);
    3022              : 
    3023       245100 :     PG_RETURN_NUMERIC(res);
    3024              : }
    3025              : 
    3026              : 
    3027              : /*
    3028              :  * numeric_mul_safe() -
    3029              :  *
    3030              :  *  Internal version of numeric_mul() with support for soft error reporting.
    3031              :  */
    3032              : Numeric
    3033       245118 : numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
    3034              : {
    3035              :     NumericVar  arg1;
    3036              :     NumericVar  arg2;
    3037              :     NumericVar  result;
    3038              :     Numeric     res;
    3039              : 
    3040              :     /*
    3041              :      * Handle NaN and infinities
    3042              :      */
    3043       245118 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3044              :     {
    3045           99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    3046           39 :             return make_result(&const_nan);
    3047           60 :         if (NUMERIC_IS_PINF(num1))
    3048              :         {
    3049           18 :             switch (numeric_sign_internal(num2))
    3050              :             {
    3051            3 :                 case 0:
    3052            3 :                     return make_result(&const_nan); /* Inf * 0 */
    3053            9 :                 case 1:
    3054            9 :                     return make_result(&const_pinf);
    3055            6 :                 case -1:
    3056            6 :                     return make_result(&const_ninf);
    3057              :             }
    3058              :             Assert(false);
    3059              :         }
    3060           42 :         if (NUMERIC_IS_NINF(num1))
    3061              :         {
    3062           18 :             switch (numeric_sign_internal(num2))
    3063              :             {
    3064            3 :                 case 0:
    3065            3 :                     return make_result(&const_nan); /* -Inf * 0 */
    3066            9 :                 case 1:
    3067            9 :                     return make_result(&const_ninf);
    3068            6 :                 case -1:
    3069            6 :                     return make_result(&const_pinf);
    3070              :             }
    3071              :             Assert(false);
    3072              :         }
    3073              :         /* by here, num1 must be finite, so num2 is not */
    3074           24 :         if (NUMERIC_IS_PINF(num2))
    3075              :         {
    3076           12 :             switch (numeric_sign_internal(num1))
    3077              :             {
    3078            3 :                 case 0:
    3079            3 :                     return make_result(&const_nan); /* 0 * Inf */
    3080            6 :                 case 1:
    3081            6 :                     return make_result(&const_pinf);
    3082            3 :                 case -1:
    3083            3 :                     return make_result(&const_ninf);
    3084              :             }
    3085              :             Assert(false);
    3086              :         }
    3087              :         Assert(NUMERIC_IS_NINF(num2));
    3088           12 :         switch (numeric_sign_internal(num1))
    3089              :         {
    3090            3 :             case 0:
    3091            3 :                 return make_result(&const_nan); /* 0 * -Inf */
    3092            6 :             case 1:
    3093            6 :                 return make_result(&const_ninf);
    3094            3 :             case -1:
    3095            3 :                 return make_result(&const_pinf);
    3096              :         }
    3097              :         Assert(false);
    3098              :     }
    3099              : 
    3100              :     /*
    3101              :      * Unpack the values, let mul_var() compute the result and return it.
    3102              :      * Unlike add_var() and sub_var(), mul_var() will round its result. In the
    3103              :      * case of numeric_mul(), which is invoked for the * operator on numerics,
    3104              :      * we request exact representation for the product (rscale = sum(dscale of
    3105              :      * arg1, dscale of arg2)).  If the exact result has more digits after the
    3106              :      * decimal point than can be stored in a numeric, we round it.  Rounding
    3107              :      * after computing the exact result ensures that the final result is
    3108              :      * correctly rounded (rounding in mul_var() using a truncated product
    3109              :      * would not guarantee this).
    3110              :      */
    3111       245019 :     init_var_from_num(num1, &arg1);
    3112       245019 :     init_var_from_num(num2, &arg2);
    3113              : 
    3114       245019 :     init_var(&result);
    3115       245019 :     mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
    3116              : 
    3117       245019 :     if (result.dscale > NUMERIC_DSCALE_MAX)
    3118            3 :         round_var(&result, NUMERIC_DSCALE_MAX);
    3119              : 
    3120       245019 :     res = make_result_safe(&result, escontext);
    3121              : 
    3122       245019 :     free_var(&result);
    3123              : 
    3124       245019 :     return res;
    3125              : }
    3126              : 
    3127              : 
    3128              : /*
    3129              :  * numeric_div() -
    3130              :  *
    3131              :  *  Divide one numeric into another
    3132              :  */
    3133              : Datum
    3134        74159 : numeric_div(PG_FUNCTION_ARGS)
    3135              : {
    3136        74159 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3137        74159 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3138              :     Numeric     res;
    3139              : 
    3140        74159 :     res = numeric_div_safe(num1, num2, NULL);
    3141              : 
    3142        74143 :     PG_RETURN_NUMERIC(res);
    3143              : }
    3144              : 
    3145              : 
    3146              : /*
    3147              :  * numeric_div_safe() -
    3148              :  *
    3149              :  *  Internal version of numeric_div() with support for soft error reporting.
    3150              :  */
    3151              : Numeric
    3152        74579 : numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
    3153              : {
    3154              :     NumericVar  arg1;
    3155              :     NumericVar  arg2;
    3156              :     NumericVar  result;
    3157              :     Numeric     res;
    3158              :     int         rscale;
    3159              : 
    3160              :     /*
    3161              :      * Handle NaN and infinities
    3162              :      */
    3163        74579 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3164              :     {
    3165           99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    3166           39 :             return make_result(&const_nan);
    3167           60 :         if (NUMERIC_IS_PINF(num1))
    3168              :         {
    3169           18 :             if (NUMERIC_IS_SPECIAL(num2))
    3170            6 :                 return make_result(&const_nan); /* Inf / [-]Inf */
    3171           12 :             switch (numeric_sign_internal(num2))
    3172              :             {
    3173            3 :                 case 0:
    3174            3 :                     goto division_by_zero;
    3175            6 :                 case 1:
    3176            6 :                     return make_result(&const_pinf);
    3177            3 :                 case -1:
    3178            3 :                     return make_result(&const_ninf);
    3179              :             }
    3180              :             Assert(false);
    3181              :         }
    3182           42 :         if (NUMERIC_IS_NINF(num1))
    3183              :         {
    3184           18 :             if (NUMERIC_IS_SPECIAL(num2))
    3185            6 :                 return make_result(&const_nan); /* -Inf / [-]Inf */
    3186           12 :             switch (numeric_sign_internal(num2))
    3187              :             {
    3188            3 :                 case 0:
    3189            3 :                     goto division_by_zero;
    3190            6 :                 case 1:
    3191            6 :                     return make_result(&const_ninf);
    3192            3 :                 case -1:
    3193            3 :                     return make_result(&const_pinf);
    3194              :             }
    3195              :             Assert(false);
    3196              :         }
    3197              :         /* by here, num1 must be finite, so num2 is not */
    3198              : 
    3199              :         /*
    3200              :          * POSIX would have us return zero or minus zero if num1 is zero, and
    3201              :          * otherwise throw an underflow error.  But the numeric type doesn't
    3202              :          * really do underflow, so let's just return zero.
    3203              :          */
    3204           24 :         return make_result(&const_zero);
    3205              :     }
    3206              : 
    3207              :     /*
    3208              :      * Unpack the arguments
    3209              :      */
    3210        74480 :     init_var_from_num(num1, &arg1);
    3211        74480 :     init_var_from_num(num2, &arg2);
    3212              : 
    3213        74480 :     init_var(&result);
    3214              : 
    3215              :     /*
    3216              :      * Select scale for division result
    3217              :      */
    3218        74480 :     rscale = select_div_scale(&arg1, &arg2);
    3219              : 
    3220              :     /* Check for division by zero */
    3221        74480 :     if (arg2.ndigits == 0 || arg2.digits[0] == 0)
    3222           25 :         goto division_by_zero;
    3223              : 
    3224              :     /*
    3225              :      * Do the divide and return the result
    3226              :      */
    3227        74455 :     div_var(&arg1, &arg2, &result, rscale, true, true);
    3228              : 
    3229        74455 :     res = make_result_safe(&result, escontext);
    3230              : 
    3231        74455 :     free_var(&result);
    3232              : 
    3233        74455 :     return res;
    3234              : 
    3235           31 : division_by_zero:
    3236           31 :     ereturn(escontext, NULL,
    3237              :             errcode(ERRCODE_DIVISION_BY_ZERO),
    3238              :             errmsg("division by zero"));
    3239              : }
    3240              : 
    3241              : 
    3242              : /*
    3243              :  * numeric_div_trunc() -
    3244              :  *
    3245              :  *  Divide one numeric into another, truncating the result to an integer
    3246              :  */
    3247              : Datum
    3248          609 : numeric_div_trunc(PG_FUNCTION_ARGS)
    3249              : {
    3250          609 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3251          609 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3252              :     NumericVar  arg1;
    3253              :     NumericVar  arg2;
    3254              :     NumericVar  result;
    3255              :     Numeric     res;
    3256              : 
    3257              :     /*
    3258              :      * Handle NaN and infinities
    3259              :      */
    3260          609 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3261              :     {
    3262           99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    3263           39 :             PG_RETURN_NUMERIC(make_result(&const_nan));
    3264           60 :         if (NUMERIC_IS_PINF(num1))
    3265              :         {
    3266           18 :             if (NUMERIC_IS_SPECIAL(num2))
    3267            6 :                 PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
    3268           12 :             switch (numeric_sign_internal(num2))
    3269              :             {
    3270            3 :                 case 0:
    3271            3 :                     ereport(ERROR,
    3272              :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
    3273              :                              errmsg("division by zero")));
    3274              :                     break;
    3275            6 :                 case 1:
    3276            6 :                     PG_RETURN_NUMERIC(make_result(&const_pinf));
    3277            3 :                 case -1:
    3278            3 :                     PG_RETURN_NUMERIC(make_result(&const_ninf));
    3279              :             }
    3280              :             Assert(false);
    3281              :         }
    3282           42 :         if (NUMERIC_IS_NINF(num1))
    3283              :         {
    3284           18 :             if (NUMERIC_IS_SPECIAL(num2))
    3285            6 :                 PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
    3286           12 :             switch (numeric_sign_internal(num2))
    3287              :             {
    3288            3 :                 case 0:
    3289            3 :                     ereport(ERROR,
    3290              :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
    3291              :                              errmsg("division by zero")));
    3292              :                     break;
    3293            6 :                 case 1:
    3294            6 :                     PG_RETURN_NUMERIC(make_result(&const_ninf));
    3295            3 :                 case -1:
    3296            3 :                     PG_RETURN_NUMERIC(make_result(&const_pinf));
    3297              :             }
    3298              :             Assert(false);
    3299              :         }
    3300              :         /* by here, num1 must be finite, so num2 is not */
    3301              : 
    3302              :         /*
    3303              :          * POSIX would have us return zero or minus zero if num1 is zero, and
    3304              :          * otherwise throw an underflow error.  But the numeric type doesn't
    3305              :          * really do underflow, so let's just return zero.
    3306              :          */
    3307           24 :         PG_RETURN_NUMERIC(make_result(&const_zero));
    3308              :     }
    3309              : 
    3310              :     /*
    3311              :      * Unpack the arguments
    3312              :      */
    3313          510 :     init_var_from_num(num1, &arg1);
    3314          510 :     init_var_from_num(num2, &arg2);
    3315              : 
    3316          510 :     init_var(&result);
    3317              : 
    3318              :     /*
    3319              :      * Do the divide and return the result
    3320              :      */
    3321          510 :     div_var(&arg1, &arg2, &result, 0, false, true);
    3322              : 
    3323          507 :     res = make_result(&result);
    3324              : 
    3325          507 :     free_var(&result);
    3326              : 
    3327          507 :     PG_RETURN_NUMERIC(res);
    3328              : }
    3329              : 
    3330              : 
    3331              : /*
    3332              :  * numeric_mod() -
    3333              :  *
    3334              :  *  Calculate the modulo of two numerics
    3335              :  */
    3336              : Datum
    3337       206705 : numeric_mod(PG_FUNCTION_ARGS)
    3338              : {
    3339       206705 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3340       206705 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3341              :     Numeric     res;
    3342              : 
    3343       206705 :     res = numeric_mod_safe(num1, num2, NULL);
    3344              : 
    3345       206696 :     PG_RETURN_NUMERIC(res);
    3346              : }
    3347              : 
    3348              : 
    3349              : /*
    3350              :  * numeric_mod_safe() -
    3351              :  *
    3352              :  *  Internal version of numeric_mod() with support for soft error reporting.
    3353              :  */
    3354              : Numeric
    3355       206711 : numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
    3356              : {
    3357              :     Numeric     res;
    3358              :     NumericVar  arg1;
    3359              :     NumericVar  arg2;
    3360              :     NumericVar  result;
    3361              : 
    3362              :     /*
    3363              :      * Handle NaN and infinities.  We follow POSIX fmod() on this, except that
    3364              :      * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
    3365              :      * returning NaN.  We choose to throw error only for y-is-zero.
    3366              :      */
    3367       206711 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3368              :     {
    3369           99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    3370           39 :             return make_result(&const_nan);
    3371           60 :         if (NUMERIC_IS_INF(num1))
    3372              :         {
    3373           36 :             if (numeric_sign_internal(num2) == 0)
    3374            6 :                 goto division_by_zero;
    3375              : 
    3376              :             /* Inf % any nonzero = NaN */
    3377           30 :             return make_result(&const_nan);
    3378              :         }
    3379              :         /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
    3380           24 :         return duplicate_numeric(num1);
    3381              :     }
    3382              : 
    3383       206612 :     init_var_from_num(num1, &arg1);
    3384       206612 :     init_var_from_num(num2, &arg2);
    3385              : 
    3386       206612 :     init_var(&result);
    3387              : 
    3388              :     /* Check for division by zero */
    3389       206612 :     if (arg2.ndigits == 0 || arg2.digits[0] == 0)
    3390            6 :         goto division_by_zero;
    3391              : 
    3392       206606 :     mod_var(&arg1, &arg2, &result);
    3393              : 
    3394       206606 :     res = make_result_safe(&result, escontext);
    3395              : 
    3396       206606 :     free_var(&result);
    3397              : 
    3398       206606 :     return res;
    3399              : 
    3400           12 : division_by_zero:
    3401           12 :     ereturn(escontext, NULL,
    3402              :             errcode(ERRCODE_DIVISION_BY_ZERO),
    3403              :             errmsg("division by zero"));
    3404              : }
    3405              : 
    3406              : 
    3407              : /*
    3408              :  * numeric_inc() -
    3409              :  *
    3410              :  *  Increment a number by one
    3411              :  */
    3412              : Datum
    3413           24 : numeric_inc(PG_FUNCTION_ARGS)
    3414              : {
    3415           24 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3416              :     NumericVar  arg;
    3417              :     Numeric     res;
    3418              : 
    3419              :     /*
    3420              :      * Handle NaN and infinities
    3421              :      */
    3422           24 :     if (NUMERIC_IS_SPECIAL(num))
    3423            9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    3424              : 
    3425              :     /*
    3426              :      * Compute the result and return it
    3427              :      */
    3428           15 :     init_var_from_num(num, &arg);
    3429              : 
    3430           15 :     add_var(&arg, &const_one, &arg);
    3431              : 
    3432           15 :     res = make_result(&arg);
    3433              : 
    3434           15 :     free_var(&arg);
    3435              : 
    3436           15 :     PG_RETURN_NUMERIC(res);
    3437              : }
    3438              : 
    3439              : 
    3440              : /*
    3441              :  * numeric_smaller() -
    3442              :  *
    3443              :  *  Return the smaller of two numbers
    3444              :  */
    3445              : Datum
    3446          405 : numeric_smaller(PG_FUNCTION_ARGS)
    3447              : {
    3448          405 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3449          405 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3450              : 
    3451              :     /*
    3452              :      * Use cmp_numerics so that this will agree with the comparison operators,
    3453              :      * particularly as regards comparisons involving NaN.
    3454              :      */
    3455          405 :     if (cmp_numerics(num1, num2) < 0)
    3456          325 :         PG_RETURN_NUMERIC(num1);
    3457              :     else
    3458           80 :         PG_RETURN_NUMERIC(num2);
    3459              : }
    3460              : 
    3461              : 
    3462              : /*
    3463              :  * numeric_larger() -
    3464              :  *
    3465              :  *  Return the larger of two numbers
    3466              :  */
    3467              : Datum
    3468         9315 : numeric_larger(PG_FUNCTION_ARGS)
    3469              : {
    3470         9315 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3471         9315 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3472              : 
    3473              :     /*
    3474              :      * Use cmp_numerics so that this will agree with the comparison operators,
    3475              :      * particularly as regards comparisons involving NaN.
    3476              :      */
    3477         9315 :     if (cmp_numerics(num1, num2) > 0)
    3478         8904 :         PG_RETURN_NUMERIC(num1);
    3479              :     else
    3480          411 :         PG_RETURN_NUMERIC(num2);
    3481              : }
    3482              : 
    3483              : 
    3484              : /* ----------------------------------------------------------------------
    3485              :  *
    3486              :  * Advanced math functions
    3487              :  *
    3488              :  * ----------------------------------------------------------------------
    3489              :  */
    3490              : 
    3491              : /*
    3492              :  * numeric_gcd() -
    3493              :  *
    3494              :  *  Calculate the greatest common divisor of two numerics
    3495              :  */
    3496              : Datum
    3497          108 : numeric_gcd(PG_FUNCTION_ARGS)
    3498              : {
    3499          108 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3500          108 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3501              :     NumericVar  arg1;
    3502              :     NumericVar  arg2;
    3503              :     NumericVar  result;
    3504              :     Numeric     res;
    3505              : 
    3506              :     /*
    3507              :      * Handle NaN and infinities: we consider the result to be NaN in all such
    3508              :      * cases.
    3509              :      */
    3510          108 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3511           48 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3512              : 
    3513              :     /*
    3514              :      * Unpack the arguments
    3515              :      */
    3516           60 :     init_var_from_num(num1, &arg1);
    3517           60 :     init_var_from_num(num2, &arg2);
    3518              : 
    3519           60 :     init_var(&result);
    3520              : 
    3521              :     /*
    3522              :      * Find the GCD and return the result
    3523              :      */
    3524           60 :     gcd_var(&arg1, &arg2, &result);
    3525              : 
    3526           60 :     res = make_result(&result);
    3527              : 
    3528           60 :     free_var(&result);
    3529              : 
    3530           60 :     PG_RETURN_NUMERIC(res);
    3531              : }
    3532              : 
    3533              : 
    3534              : /*
    3535              :  * numeric_lcm() -
    3536              :  *
    3537              :  *  Calculate the least common multiple of two numerics
    3538              :  */
    3539              : Datum
    3540          123 : numeric_lcm(PG_FUNCTION_ARGS)
    3541              : {
    3542          123 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3543          123 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3544              :     NumericVar  arg1;
    3545              :     NumericVar  arg2;
    3546              :     NumericVar  result;
    3547              :     Numeric     res;
    3548              : 
    3549              :     /*
    3550              :      * Handle NaN and infinities: we consider the result to be NaN in all such
    3551              :      * cases.
    3552              :      */
    3553          123 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3554           48 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    3555              : 
    3556              :     /*
    3557              :      * Unpack the arguments
    3558              :      */
    3559           75 :     init_var_from_num(num1, &arg1);
    3560           75 :     init_var_from_num(num2, &arg2);
    3561              : 
    3562           75 :     init_var(&result);
    3563              : 
    3564              :     /*
    3565              :      * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
    3566              :      * zero if either input is zero.
    3567              :      *
    3568              :      * Note that the division is guaranteed to be exact, returning an integer
    3569              :      * result, so the LCM is an integral multiple of both x and y.  A display
    3570              :      * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
    3571              :      * but as with other numeric functions, we choose to return a result whose
    3572              :      * display scale is no smaller than either input.
    3573              :      */
    3574           75 :     if (arg1.ndigits == 0 || arg2.ndigits == 0)
    3575           24 :         set_var_from_var(&const_zero, &result);
    3576              :     else
    3577              :     {
    3578           51 :         gcd_var(&arg1, &arg2, &result);
    3579           51 :         div_var(&arg1, &result, &result, 0, false, true);
    3580           51 :         mul_var(&arg2, &result, &result, arg2.dscale);
    3581           51 :         result.sign = NUMERIC_POS;
    3582              :     }
    3583              : 
    3584           75 :     result.dscale = Max(arg1.dscale, arg2.dscale);
    3585              : 
    3586           75 :     res = make_result(&result);
    3587              : 
    3588           72 :     free_var(&result);
    3589              : 
    3590           72 :     PG_RETURN_NUMERIC(res);
    3591              : }
    3592              : 
    3593              : 
    3594              : /*
    3595              :  * numeric_fac()
    3596              :  *
    3597              :  * Compute factorial
    3598              :  */
    3599              : Datum
    3600           21 : numeric_fac(PG_FUNCTION_ARGS)
    3601              : {
    3602           21 :     int64       num = PG_GETARG_INT64(0);
    3603              :     Numeric     res;
    3604              :     NumericVar  fact;
    3605              :     NumericVar  result;
    3606              : 
    3607           21 :     if (num < 0)
    3608            3 :         ereport(ERROR,
    3609              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    3610              :                  errmsg("factorial of a negative number is undefined")));
    3611           18 :     if (num <= 1)
    3612              :     {
    3613            3 :         res = make_result(&const_one);
    3614            3 :         PG_RETURN_NUMERIC(res);
    3615              :     }
    3616              :     /* Fail immediately if the result would overflow */
    3617           15 :     if (num > 32177)
    3618            3 :         ereport(ERROR,
    3619              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    3620              :                  errmsg("value overflows numeric format")));
    3621              : 
    3622           12 :     init_var(&fact);
    3623           12 :     init_var(&result);
    3624              : 
    3625           12 :     int64_to_numericvar(num, &result);
    3626              : 
    3627          147 :     for (num = num - 1; num > 1; num--)
    3628              :     {
    3629              :         /* this loop can take awhile, so allow it to be interrupted */
    3630          135 :         CHECK_FOR_INTERRUPTS();
    3631              : 
    3632          135 :         int64_to_numericvar(num, &fact);
    3633              : 
    3634          135 :         mul_var(&result, &fact, &result, 0);
    3635              :     }
    3636              : 
    3637           12 :     res = make_result(&result);
    3638              : 
    3639           12 :     free_var(&fact);
    3640           12 :     free_var(&result);
    3641              : 
    3642           12 :     PG_RETURN_NUMERIC(res);
    3643              : }
    3644              : 
    3645              : 
    3646              : /*
    3647              :  * numeric_sqrt() -
    3648              :  *
    3649              :  *  Compute the square root of a numeric.
    3650              :  */
    3651              : Datum
    3652           75 : numeric_sqrt(PG_FUNCTION_ARGS)
    3653              : {
    3654           75 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3655              :     Numeric     res;
    3656              :     NumericVar  arg;
    3657              :     NumericVar  result;
    3658              :     int         sweight;
    3659              :     int         rscale;
    3660              : 
    3661              :     /*
    3662              :      * Handle NaN and infinities
    3663              :      */
    3664           75 :     if (NUMERIC_IS_SPECIAL(num))
    3665              :     {
    3666              :         /* error should match that in sqrt_var() */
    3667            9 :         if (NUMERIC_IS_NINF(num))
    3668            3 :             ereport(ERROR,
    3669              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    3670              :                      errmsg("cannot take square root of a negative number")));
    3671              :         /* For NAN or PINF, just duplicate the input */
    3672            6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    3673              :     }
    3674              : 
    3675              :     /*
    3676              :      * Unpack the argument and determine the result scale.  We choose a scale
    3677              :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
    3678              :      * case not less than the input's dscale.
    3679              :      */
    3680           66 :     init_var_from_num(num, &arg);
    3681              : 
    3682           66 :     init_var(&result);
    3683              : 
    3684              :     /*
    3685              :      * Assume the input was normalized, so arg.weight is accurate.  The result
    3686              :      * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
    3687              :      * digits before the decimal point.  When DEC_DIGITS is even, we can save
    3688              :      * a few cycles, since the division is exact and there is no need to round
    3689              :      * towards negative infinity.
    3690              :      */
    3691              : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
    3692           66 :     sweight = arg.weight * DEC_DIGITS / 2 + 1;
    3693              : #else
    3694              :     if (arg.weight >= 0)
    3695              :         sweight = arg.weight * DEC_DIGITS / 2 + 1;
    3696              :     else
    3697              :         sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
    3698              : #endif
    3699              : 
    3700           66 :     rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
    3701           66 :     rscale = Max(rscale, arg.dscale);
    3702           66 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    3703           66 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    3704              : 
    3705              :     /*
    3706              :      * Let sqrt_var() do the calculation and return the result.
    3707              :      */
    3708           66 :     sqrt_var(&arg, &result, rscale);
    3709              : 
    3710           63 :     res = make_result(&result);
    3711              : 
    3712           63 :     free_var(&result);
    3713              : 
    3714           63 :     PG_RETURN_NUMERIC(res);
    3715              : }
    3716              : 
    3717              : 
    3718              : /*
    3719              :  * numeric_exp() -
    3720              :  *
    3721              :  *  Raise e to the power of x
    3722              :  */
    3723              : Datum
    3724           39 : numeric_exp(PG_FUNCTION_ARGS)
    3725              : {
    3726           39 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3727              :     Numeric     res;
    3728              :     NumericVar  arg;
    3729              :     NumericVar  result;
    3730              :     int         rscale;
    3731              :     double      val;
    3732              : 
    3733              :     /*
    3734              :      * Handle NaN and infinities
    3735              :      */
    3736           39 :     if (NUMERIC_IS_SPECIAL(num))
    3737              :     {
    3738              :         /* Per POSIX, exp(-Inf) is zero */
    3739            9 :         if (NUMERIC_IS_NINF(num))
    3740            3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
    3741              :         /* For NAN or PINF, just duplicate the input */
    3742            6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    3743              :     }
    3744              : 
    3745              :     /*
    3746              :      * Unpack the argument and determine the result scale.  We choose a scale
    3747              :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
    3748              :      * case not less than the input's dscale.
    3749              :      */
    3750           30 :     init_var_from_num(num, &arg);
    3751              : 
    3752           30 :     init_var(&result);
    3753              : 
    3754              :     /* convert input to float8, ignoring overflow */
    3755           30 :     val = numericvar_to_double_no_overflow(&arg);
    3756              : 
    3757              :     /*
    3758              :      * log10(result) = num * log10(e), so this is approximately the decimal
    3759              :      * weight of the result:
    3760              :      */
    3761           30 :     val *= 0.434294481903252;
    3762              : 
    3763              :     /* limit to something that won't cause integer overflow */
    3764           30 :     val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
    3765           30 :     val = Min(val, NUMERIC_MAX_RESULT_SCALE);
    3766              : 
    3767           30 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
    3768           30 :     rscale = Max(rscale, arg.dscale);
    3769           30 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    3770           30 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    3771              : 
    3772              :     /*
    3773              :      * Let exp_var() do the calculation and return the result.
    3774              :      */
    3775           30 :     exp_var(&arg, &result, rscale);
    3776              : 
    3777           30 :     res = make_result(&result);
    3778              : 
    3779           30 :     free_var(&result);
    3780              : 
    3781           30 :     PG_RETURN_NUMERIC(res);
    3782              : }
    3783              : 
    3784              : 
    3785              : /*
    3786              :  * numeric_ln() -
    3787              :  *
    3788              :  *  Compute the natural logarithm of x
    3789              :  */
    3790              : Datum
    3791           99 : numeric_ln(PG_FUNCTION_ARGS)
    3792              : {
    3793           99 :     Numeric     num = PG_GETARG_NUMERIC(0);
    3794              :     Numeric     res;
    3795              :     NumericVar  arg;
    3796              :     NumericVar  result;
    3797              :     int         ln_dweight;
    3798              :     int         rscale;
    3799              : 
    3800              :     /*
    3801              :      * Handle NaN and infinities
    3802              :      */
    3803           99 :     if (NUMERIC_IS_SPECIAL(num))
    3804              :     {
    3805            9 :         if (NUMERIC_IS_NINF(num))
    3806            3 :             ereport(ERROR,
    3807              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    3808              :                      errmsg("cannot take logarithm of a negative number")));
    3809              :         /* For NAN or PINF, just duplicate the input */
    3810            6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    3811              :     }
    3812              : 
    3813           90 :     init_var_from_num(num, &arg);
    3814           90 :     init_var(&result);
    3815              : 
    3816              :     /* Estimated dweight of logarithm */
    3817           90 :     ln_dweight = estimate_ln_dweight(&arg);
    3818              : 
    3819           90 :     rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
    3820           90 :     rscale = Max(rscale, arg.dscale);
    3821           90 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    3822           90 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    3823              : 
    3824           90 :     ln_var(&arg, &result, rscale);
    3825              : 
    3826           78 :     res = make_result(&result);
    3827              : 
    3828           78 :     free_var(&result);
    3829              : 
    3830           78 :     PG_RETURN_NUMERIC(res);
    3831              : }
    3832              : 
    3833              : 
    3834              : /*
    3835              :  * numeric_log() -
    3836              :  *
    3837              :  *  Compute the logarithm of x in a given base
    3838              :  */
    3839              : Datum
    3840          171 : numeric_log(PG_FUNCTION_ARGS)
    3841              : {
    3842          171 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3843          171 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3844              :     Numeric     res;
    3845              :     NumericVar  arg1;
    3846              :     NumericVar  arg2;
    3847              :     NumericVar  result;
    3848              : 
    3849              :     /*
    3850              :      * Handle NaN and infinities
    3851              :      */
    3852          171 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3853              :     {
    3854              :         int         sign1,
    3855              :                     sign2;
    3856              : 
    3857           63 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
    3858           27 :             PG_RETURN_NUMERIC(make_result(&const_nan));
    3859              :         /* fail on negative inputs including -Inf, as log_var would */
    3860           36 :         sign1 = numeric_sign_internal(num1);
    3861           36 :         sign2 = numeric_sign_internal(num2);
    3862           36 :         if (sign1 < 0 || sign2 < 0)
    3863           12 :             ereport(ERROR,
    3864              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    3865              :                      errmsg("cannot take logarithm of a negative number")));
    3866              :         /* fail on zero inputs, as log_var would */
    3867           24 :         if (sign1 == 0 || sign2 == 0)
    3868            3 :             ereport(ERROR,
    3869              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
    3870              :                      errmsg("cannot take logarithm of zero")));
    3871           21 :         if (NUMERIC_IS_PINF(num1))
    3872              :         {
    3873              :             /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
    3874            9 :             if (NUMERIC_IS_PINF(num2))
    3875            3 :                 PG_RETURN_NUMERIC(make_result(&const_nan));
    3876              :             /* log(Inf, finite-positive) is zero (we don't throw underflow) */
    3877            6 :             PG_RETURN_NUMERIC(make_result(&const_zero));
    3878              :         }
    3879              :         Assert(NUMERIC_IS_PINF(num2));
    3880              :         /* log(finite-positive, Inf) is Inf */
    3881           12 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
    3882              :     }
    3883              : 
    3884              :     /*
    3885              :      * Initialize things
    3886              :      */
    3887          108 :     init_var_from_num(num1, &arg1);
    3888          108 :     init_var_from_num(num2, &arg2);
    3889          108 :     init_var(&result);
    3890              : 
    3891              :     /*
    3892              :      * Call log_var() to compute and return the result; note it handles scale
    3893              :      * selection itself.
    3894              :      */
    3895          108 :     log_var(&arg1, &arg2, &result);
    3896              : 
    3897           78 :     res = make_result(&result);
    3898              : 
    3899           78 :     free_var(&result);
    3900              : 
    3901           78 :     PG_RETURN_NUMERIC(res);
    3902              : }
    3903              : 
    3904              : 
    3905              : /*
    3906              :  * numeric_power() -
    3907              :  *
    3908              :  *  Raise x to the power of y
    3909              :  */
    3910              : Datum
    3911          822 : numeric_power(PG_FUNCTION_ARGS)
    3912              : {
    3913          822 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
    3914          822 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
    3915              :     Numeric     res;
    3916              :     NumericVar  arg1;
    3917              :     NumericVar  arg2;
    3918              :     NumericVar  result;
    3919              :     int         sign1,
    3920              :                 sign2;
    3921              : 
    3922              :     /*
    3923              :      * Handle NaN and infinities
    3924              :      */
    3925          822 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
    3926              :     {
    3927              :         /*
    3928              :          * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
    3929              :          * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
    3930              :          * (with no error).
    3931              :          */
    3932          117 :         if (NUMERIC_IS_NAN(num1))
    3933              :         {
    3934           27 :             if (!NUMERIC_IS_SPECIAL(num2))
    3935              :             {
    3936           18 :                 init_var_from_num(num2, &arg2);
    3937           18 :                 if (cmp_var(&arg2, &const_zero) == 0)
    3938            6 :                     PG_RETURN_NUMERIC(make_result(&const_one));
    3939              :             }
    3940           21 :             PG_RETURN_NUMERIC(make_result(&const_nan));
    3941              :         }
    3942           90 :         if (NUMERIC_IS_NAN(num2))
    3943              :         {
    3944           21 :             if (!NUMERIC_IS_SPECIAL(num1))
    3945              :             {
    3946           18 :                 init_var_from_num(num1, &arg1);
    3947           18 :                 if (cmp_var(&arg1, &const_one) == 0)
    3948            6 :                     PG_RETURN_NUMERIC(make_result(&const_one));
    3949              :             }
    3950           15 :             PG_RETURN_NUMERIC(make_result(&const_nan));
    3951              :         }
    3952              :         /* At least one input is infinite, but error rules still apply */
    3953           69 :         sign1 = numeric_sign_internal(num1);
    3954           69 :         sign2 = numeric_sign_internal(num2);
    3955           69 :         if (sign1 == 0 && sign2 < 0)
    3956            3 :             ereport(ERROR,
    3957              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    3958              :                      errmsg("zero raised to a negative power is undefined")));
    3959           66 :         if (sign1 < 0 && !numeric_is_integral(num2))
    3960            3 :             ereport(ERROR,
    3961              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    3962              :                      errmsg("a negative number raised to a non-integer power yields a complex result")));
    3963              : 
    3964              :         /*
    3965              :          * POSIX gives this series of rules for pow(3) with infinite inputs:
    3966              :          *
    3967              :          * For any value of y, if x is +1, 1.0 shall be returned.
    3968              :          */
    3969           63 :         if (!NUMERIC_IS_SPECIAL(num1))
    3970              :         {
    3971           21 :             init_var_from_num(num1, &arg1);
    3972           21 :             if (cmp_var(&arg1, &const_one) == 0)
    3973            3 :                 PG_RETURN_NUMERIC(make_result(&const_one));
    3974              :         }
    3975              : 
    3976              :         /*
    3977              :          * For any value of x, if y is [-]0, 1.0 shall be returned.
    3978              :          */
    3979           60 :         if (sign2 == 0)
    3980            6 :             PG_RETURN_NUMERIC(make_result(&const_one));
    3981              : 
    3982              :         /*
    3983              :          * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
    3984              :          * returned.  For y > 0 and not an odd integer, if x is [-]0, +0 shall
    3985              :          * be returned.  (Since we don't deal in minus zero, we need not
    3986              :          * distinguish these two cases.)
    3987              :          */
    3988           54 :         if (sign1 == 0 && sign2 > 0)
    3989            3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
    3990              : 
    3991              :         /*
    3992              :          * If x is -1, and y is [-]Inf, 1.0 shall be returned.
    3993              :          *
    3994              :          * For |x| < 1, if y is -Inf, +Inf shall be returned.
    3995              :          *
    3996              :          * For |x| > 1, if y is -Inf, +0 shall be returned.
    3997              :          *
    3998              :          * For |x| < 1, if y is +Inf, +0 shall be returned.
    3999              :          *
    4000              :          * For |x| > 1, if y is +Inf, +Inf shall be returned.
    4001              :          */
    4002           51 :         if (NUMERIC_IS_INF(num2))
    4003              :         {
    4004              :             bool        abs_x_gt_one;
    4005              : 
    4006           27 :             if (NUMERIC_IS_SPECIAL(num1))
    4007           12 :                 abs_x_gt_one = true;    /* x is either Inf or -Inf */
    4008              :             else
    4009              :             {
    4010           15 :                 init_var_from_num(num1, &arg1);
    4011           15 :                 if (cmp_var(&arg1, &const_minus_one) == 0)
    4012            3 :                     PG_RETURN_NUMERIC(make_result(&const_one));
    4013           12 :                 arg1.sign = NUMERIC_POS;    /* now arg1 = abs(x) */
    4014           12 :                 abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
    4015              :             }
    4016           24 :             if (abs_x_gt_one == (sign2 > 0))
    4017           15 :                 PG_RETURN_NUMERIC(make_result(&const_pinf));
    4018              :             else
    4019            9 :                 PG_RETURN_NUMERIC(make_result(&const_zero));
    4020              :         }
    4021              : 
    4022              :         /*
    4023              :          * For y < 0, if x is +Inf, +0 shall be returned.
    4024              :          *
    4025              :          * For y > 0, if x is +Inf, +Inf shall be returned.
    4026              :          */
    4027           24 :         if (NUMERIC_IS_PINF(num1))
    4028              :         {
    4029           12 :             if (sign2 > 0)
    4030            9 :                 PG_RETURN_NUMERIC(make_result(&const_pinf));
    4031              :             else
    4032            3 :                 PG_RETURN_NUMERIC(make_result(&const_zero));
    4033              :         }
    4034              : 
    4035              :         Assert(NUMERIC_IS_NINF(num1));
    4036              : 
    4037              :         /*
    4038              :          * For y an odd integer < 0, if x is -Inf, -0 shall be returned.  For
    4039              :          * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
    4040              :          * (Again, we need not distinguish these two cases.)
    4041              :          */
    4042           12 :         if (sign2 < 0)
    4043            6 :             PG_RETURN_NUMERIC(make_result(&const_zero));
    4044              : 
    4045              :         /*
    4046              :          * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
    4047              :          * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
    4048              :          */
    4049            6 :         init_var_from_num(num2, &arg2);
    4050            6 :         if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
    4051            6 :             (arg2.digits[arg2.ndigits - 1] & 1))
    4052            3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
    4053              :         else
    4054            3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
    4055              :     }
    4056              : 
    4057              :     /*
    4058              :      * The SQL spec requires that we emit a particular SQLSTATE error code for
    4059              :      * certain error conditions.  Specifically, we don't return a
    4060              :      * divide-by-zero error code for 0 ^ -1.  Raising a negative number to a
    4061              :      * non-integer power must produce the same error code, but that case is
    4062              :      * handled in power_var().
    4063              :      */
    4064          705 :     sign1 = numeric_sign_internal(num1);
    4065          705 :     sign2 = numeric_sign_internal(num2);
    4066              : 
    4067          705 :     if (sign1 == 0 && sign2 < 0)
    4068            6 :         ereport(ERROR,
    4069              :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    4070              :                  errmsg("zero raised to a negative power is undefined")));
    4071              : 
    4072              :     /*
    4073              :      * Initialize things
    4074              :      */
    4075          699 :     init_var(&result);
    4076          699 :     init_var_from_num(num1, &arg1);
    4077          699 :     init_var_from_num(num2, &arg2);
    4078              : 
    4079              :     /*
    4080              :      * Call power_var() to compute and return the result; note it handles
    4081              :      * scale selection itself.
    4082              :      */
    4083          699 :     power_var(&arg1, &arg2, &result);
    4084              : 
    4085          684 :     res = make_result(&result);
    4086              : 
    4087          684 :     free_var(&result);
    4088              : 
    4089          684 :     PG_RETURN_NUMERIC(res);
    4090              : }
    4091              : 
    4092              : /*
    4093              :  * numeric_scale() -
    4094              :  *
    4095              :  *  Returns the scale, i.e. the count of decimal digits in the fractional part
    4096              :  */
    4097              : Datum
    4098           54 : numeric_scale(PG_FUNCTION_ARGS)
    4099              : {
    4100           54 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4101              : 
    4102           54 :     if (NUMERIC_IS_SPECIAL(num))
    4103            9 :         PG_RETURN_NULL();
    4104              : 
    4105           45 :     PG_RETURN_INT32(NUMERIC_DSCALE(num));
    4106              : }
    4107              : 
    4108              : /*
    4109              :  * Calculate minimum scale for value.
    4110              :  */
    4111              : static int
    4112          186 : get_min_scale(NumericVar *var)
    4113              : {
    4114              :     int         min_scale;
    4115              :     int         last_digit_pos;
    4116              : 
    4117              :     /*
    4118              :      * Ordinarily, the input value will be "stripped" so that the last
    4119              :      * NumericDigit is nonzero.  But we don't want to get into an infinite
    4120              :      * loop if it isn't, so explicitly find the last nonzero digit.
    4121              :      */
    4122          186 :     last_digit_pos = var->ndigits - 1;
    4123          186 :     while (last_digit_pos >= 0 &&
    4124          171 :            var->digits[last_digit_pos] == 0)
    4125            0 :         last_digit_pos--;
    4126              : 
    4127          186 :     if (last_digit_pos >= 0)
    4128              :     {
    4129              :         /* compute min_scale assuming that last ndigit has no zeroes */
    4130          171 :         min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
    4131              : 
    4132              :         /*
    4133              :          * We could get a negative result if there are no digits after the
    4134              :          * decimal point.  In this case the min_scale must be zero.
    4135              :          */
    4136          171 :         if (min_scale > 0)
    4137              :         {
    4138              :             /*
    4139              :              * Reduce min_scale if trailing digit(s) in last NumericDigit are
    4140              :              * zero.
    4141              :              */
    4142           93 :             NumericDigit last_digit = var->digits[last_digit_pos];
    4143              : 
    4144          249 :             while (last_digit % 10 == 0)
    4145              :             {
    4146          156 :                 min_scale--;
    4147          156 :                 last_digit /= 10;
    4148              :             }
    4149              :         }
    4150              :         else
    4151           78 :             min_scale = 0;
    4152              :     }
    4153              :     else
    4154           15 :         min_scale = 0;          /* result if input is zero */
    4155              : 
    4156          186 :     return min_scale;
    4157              : }
    4158              : 
    4159              : /*
    4160              :  * Returns minimum scale required to represent supplied value without loss.
    4161              :  */
    4162              : Datum
    4163           36 : numeric_min_scale(PG_FUNCTION_ARGS)
    4164              : {
    4165           36 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4166              :     NumericVar  arg;
    4167              :     int         min_scale;
    4168              : 
    4169           36 :     if (NUMERIC_IS_SPECIAL(num))
    4170            6 :         PG_RETURN_NULL();
    4171              : 
    4172           30 :     init_var_from_num(num, &arg);
    4173           30 :     min_scale = get_min_scale(&arg);
    4174           30 :     free_var(&arg);
    4175              : 
    4176           30 :     PG_RETURN_INT32(min_scale);
    4177              : }
    4178              : 
    4179              : /*
    4180              :  * Reduce scale of numeric value to represent supplied value without loss.
    4181              :  */
    4182              : Datum
    4183          162 : numeric_trim_scale(PG_FUNCTION_ARGS)
    4184              : {
    4185          162 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4186              :     Numeric     res;
    4187              :     NumericVar  result;
    4188              : 
    4189          162 :     if (NUMERIC_IS_SPECIAL(num))
    4190            6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
    4191              : 
    4192          156 :     init_var_from_num(num, &result);
    4193          156 :     result.dscale = get_min_scale(&result);
    4194          156 :     res = make_result(&result);
    4195          156 :     free_var(&result);
    4196              : 
    4197          156 :     PG_RETURN_NUMERIC(res);
    4198              : }
    4199              : 
    4200              : /*
    4201              :  * Return a random numeric value in the range [rmin, rmax].
    4202              :  */
    4203              : Numeric
    4204        16731 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
    4205              : {
    4206              :     NumericVar  rmin_var;
    4207              :     NumericVar  rmax_var;
    4208              :     NumericVar  result;
    4209              :     Numeric     res;
    4210              : 
    4211              :     /* Range bounds must not be NaN/infinity */
    4212        16731 :     if (NUMERIC_IS_SPECIAL(rmin))
    4213              :     {
    4214            6 :         if (NUMERIC_IS_NAN(rmin))
    4215            3 :             ereport(ERROR,
    4216              :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4217              :                     errmsg("lower bound cannot be NaN"));
    4218              :         else
    4219            3 :             ereport(ERROR,
    4220              :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4221              :                     errmsg("lower bound cannot be infinity"));
    4222              :     }
    4223        16725 :     if (NUMERIC_IS_SPECIAL(rmax))
    4224              :     {
    4225            6 :         if (NUMERIC_IS_NAN(rmax))
    4226            3 :             ereport(ERROR,
    4227              :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4228              :                     errmsg("upper bound cannot be NaN"));
    4229              :         else
    4230            3 :             ereport(ERROR,
    4231              :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4232              :                     errmsg("upper bound cannot be infinity"));
    4233              :     }
    4234              : 
    4235              :     /* Return a random value in the range [rmin, rmax] */
    4236        16719 :     init_var_from_num(rmin, &rmin_var);
    4237        16719 :     init_var_from_num(rmax, &rmax_var);
    4238              : 
    4239        16719 :     init_var(&result);
    4240              : 
    4241        16719 :     random_var(state, &rmin_var, &rmax_var, &result);
    4242              : 
    4243        16716 :     res = make_result(&result);
    4244              : 
    4245        16716 :     free_var(&result);
    4246              : 
    4247        16716 :     return res;
    4248              : }
    4249              : 
    4250              : 
    4251              : /* ----------------------------------------------------------------------
    4252              :  *
    4253              :  * Type conversion functions
    4254              :  *
    4255              :  * ----------------------------------------------------------------------
    4256              :  */
    4257              : 
    4258              : Numeric
    4259       935357 : int64_to_numeric(int64 val)
    4260              : {
    4261              :     Numeric     res;
    4262              :     NumericVar  result;
    4263              : 
    4264       935357 :     init_var(&result);
    4265              : 
    4266       935357 :     int64_to_numericvar(val, &result);
    4267              : 
    4268       935357 :     res = make_result(&result);
    4269              : 
    4270       935357 :     free_var(&result);
    4271              : 
    4272       935357 :     return res;
    4273              : }
    4274              : 
    4275              : /*
    4276              :  * Convert val1/(10**log10val2) to numeric.  This is much faster than normal
    4277              :  * numeric division.
    4278              :  */
    4279              : Numeric
    4280        14692 : int64_div_fast_to_numeric(int64 val1, int log10val2)
    4281              : {
    4282              :     Numeric     res;
    4283              :     NumericVar  result;
    4284              :     int         rscale;
    4285              :     int         w;
    4286              :     int         m;
    4287              : 
    4288        14692 :     init_var(&result);
    4289              : 
    4290              :     /* result scale */
    4291        14692 :     rscale = log10val2 < 0 ? 0 : log10val2;
    4292              : 
    4293              :     /* how much to decrease the weight by */
    4294        14692 :     w = log10val2 / DEC_DIGITS;
    4295              :     /* how much is left to divide by */
    4296        14692 :     m = log10val2 % DEC_DIGITS;
    4297        14692 :     if (m < 0)
    4298              :     {
    4299            0 :         m += DEC_DIGITS;
    4300            0 :         w--;
    4301              :     }
    4302              : 
    4303              :     /*
    4304              :      * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
    4305              :      * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
    4306              :      * one more.
    4307              :      */
    4308        14692 :     if (m > 0)
    4309              :     {
    4310              : #if DEC_DIGITS == 4
    4311              :         static const int pow10[] = {1, 10, 100, 1000};
    4312              : #elif DEC_DIGITS == 2
    4313              :         static const int pow10[] = {1, 10};
    4314              : #elif DEC_DIGITS == 1
    4315              :         static const int pow10[] = {1};
    4316              : #else
    4317              : #error unsupported NBASE
    4318              : #endif
    4319        14692 :         int64       factor = pow10[DEC_DIGITS - m];
    4320              :         int64       new_val1;
    4321              : 
    4322              :         StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
    4323              : 
    4324        14692 :         if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
    4325              :         {
    4326              :             /* do the multiplication using 128-bit integers */
    4327              :             INT128      tmp;
    4328              : 
    4329            6 :             tmp = int64_to_int128(0);
    4330            6 :             int128_add_int64_mul_int64(&tmp, val1, factor);
    4331              : 
    4332            6 :             int128_to_numericvar(tmp, &result);
    4333              :         }
    4334              :         else
    4335        14686 :             int64_to_numericvar(new_val1, &result);
    4336              : 
    4337        14692 :         w++;
    4338              :     }
    4339              :     else
    4340            0 :         int64_to_numericvar(val1, &result);
    4341              : 
    4342        14692 :     result.weight -= w;
    4343        14692 :     result.dscale = rscale;
    4344              : 
    4345        14692 :     res = make_result(&result);
    4346              : 
    4347        14692 :     free_var(&result);
    4348              : 
    4349        14692 :     return res;
    4350              : }
    4351              : 
    4352              : Datum
    4353       778114 : int4_numeric(PG_FUNCTION_ARGS)
    4354              : {
    4355       778114 :     int32       val = PG_GETARG_INT32(0);
    4356              : 
    4357       778114 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
    4358              : }
    4359              : 
    4360              : /*
    4361              :  * Internal version of numeric_int4() with support for soft error reporting.
    4362              :  */
    4363              : int32
    4364         3898 : numeric_int4_safe(Numeric num, Node *escontext)
    4365              : {
    4366              :     NumericVar  x;
    4367              :     int32       result;
    4368              : 
    4369         3898 :     if (NUMERIC_IS_SPECIAL(num))
    4370              :     {
    4371            9 :         if (NUMERIC_IS_NAN(num))
    4372            3 :             ereturn(escontext, 0,
    4373              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4374              :                      errmsg("cannot convert NaN to %s", "integer")));
    4375              :         else
    4376            6 :             ereturn(escontext, 0,
    4377              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4378              :                      errmsg("cannot convert infinity to %s", "integer")));
    4379              :     }
    4380              : 
    4381              :     /* Convert to variable format, then convert to int4 */
    4382         3889 :     init_var_from_num(num, &x);
    4383              : 
    4384         3889 :     if (!numericvar_to_int32(&x, &result))
    4385           45 :         ereturn(escontext, 0,
    4386              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    4387              :                  errmsg("integer out of range")));
    4388              : 
    4389         3844 :     return result;
    4390              : }
    4391              : 
    4392              : Datum
    4393         3106 : numeric_int4(PG_FUNCTION_ARGS)
    4394              : {
    4395         3106 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4396              : 
    4397         3106 :     PG_RETURN_INT32(numeric_int4_safe(num, NULL));
    4398              : }
    4399              : 
    4400              : /*
    4401              :  * Given a NumericVar, convert it to an int32. If the NumericVar
    4402              :  * exceeds the range of an int32, false is returned, otherwise true is returned.
    4403              :  * The input NumericVar is *not* free'd.
    4404              :  */
    4405              : static bool
    4406         4261 : numericvar_to_int32(const NumericVar *var, int32 *result)
    4407              : {
    4408              :     int64       val;
    4409              : 
    4410         4261 :     if (!numericvar_to_int64(var, &val))
    4411            3 :         return false;
    4412              : 
    4413         4258 :     if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
    4414           42 :         return false;
    4415              : 
    4416              :     /* Down-convert to int4 */
    4417         4216 :     *result = (int32) val;
    4418              : 
    4419         4216 :     return true;
    4420              : }
    4421              : 
    4422              : Datum
    4423        18427 : int8_numeric(PG_FUNCTION_ARGS)
    4424              : {
    4425        18427 :     int64       val = PG_GETARG_INT64(0);
    4426              : 
    4427        18427 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
    4428              : }
    4429              : 
    4430              : /*
    4431              :  * Internal version of numeric_int8() with support for soft error reporting.
    4432              :  */
    4433              : int64
    4434          285 : numeric_int8_safe(Numeric num, Node *escontext)
    4435              : {
    4436              :     NumericVar  x;
    4437              :     int64       result;
    4438              : 
    4439          285 :     if (NUMERIC_IS_SPECIAL(num))
    4440              :     {
    4441            9 :         if (NUMERIC_IS_NAN(num))
    4442            3 :             ereturn(escontext, 0,
    4443              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4444              :                      errmsg("cannot convert NaN to %s", "bigint")));
    4445              :         else
    4446            6 :             ereturn(escontext, 0,
    4447              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4448              :                      errmsg("cannot convert infinity to %s", "bigint")));
    4449              :     }
    4450              : 
    4451              :     /* Convert to variable format, then convert to int8 */
    4452          276 :     init_var_from_num(num, &x);
    4453              : 
    4454          276 :     if (!numericvar_to_int64(&x, &result))
    4455           30 :         ereturn(escontext, 0,
    4456              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    4457              :                  errmsg("bigint out of range")));
    4458              : 
    4459          246 :     return result;
    4460              : }
    4461              : 
    4462              : Datum
    4463          261 : numeric_int8(PG_FUNCTION_ARGS)
    4464              : {
    4465          261 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4466              : 
    4467          261 :     PG_RETURN_INT64(numeric_int8_safe(num, NULL));
    4468              : }
    4469              : 
    4470              : 
    4471              : Datum
    4472            3 : int2_numeric(PG_FUNCTION_ARGS)
    4473              : {
    4474            3 :     int16       val = PG_GETARG_INT16(0);
    4475              : 
    4476            3 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
    4477              : }
    4478              : 
    4479              : 
    4480              : Datum
    4481           51 : numeric_int2(PG_FUNCTION_ARGS)
    4482              : {
    4483           51 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4484              :     NumericVar  x;
    4485              :     int64       val;
    4486              :     int16       result;
    4487              : 
    4488           51 :     if (NUMERIC_IS_SPECIAL(num))
    4489              :     {
    4490            9 :         if (NUMERIC_IS_NAN(num))
    4491            3 :             ereport(ERROR,
    4492              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4493              :                      errmsg("cannot convert NaN to %s", "smallint")));
    4494              :         else
    4495            6 :             ereport(ERROR,
    4496              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4497              :                      errmsg("cannot convert infinity to %s", "smallint")));
    4498              :     }
    4499              : 
    4500              :     /* Convert to variable format and thence to int8 */
    4501           42 :     init_var_from_num(num, &x);
    4502              : 
    4503           42 :     if (!numericvar_to_int64(&x, &val))
    4504            0 :         ereport(ERROR,
    4505              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    4506              :                  errmsg("smallint out of range")));
    4507              : 
    4508           42 :     if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
    4509            6 :         ereport(ERROR,
    4510              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    4511              :                  errmsg("smallint out of range")));
    4512              : 
    4513              :     /* Down-convert to int2 */
    4514           36 :     result = (int16) val;
    4515              : 
    4516           36 :     PG_RETURN_INT16(result);
    4517              : }
    4518              : 
    4519              : 
    4520              : Datum
    4521          537 : float8_numeric(PG_FUNCTION_ARGS)
    4522              : {
    4523          537 :     float8      val = PG_GETARG_FLOAT8(0);
    4524              :     Numeric     res;
    4525              :     NumericVar  result;
    4526              :     char        buf[DBL_DIG + 100];
    4527              :     const char *endptr;
    4528              : 
    4529          537 :     if (isnan(val))
    4530            3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    4531              : 
    4532          534 :     if (isinf(val))
    4533              :     {
    4534            6 :         if (val < 0)
    4535            3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
    4536              :         else
    4537            3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
    4538              :     }
    4539              : 
    4540          528 :     snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
    4541              : 
    4542          528 :     init_var(&result);
    4543              : 
    4544              :     /* Assume we need not worry about leading/trailing spaces */
    4545          528 :     (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
    4546              : 
    4547          528 :     res = make_result(&result);
    4548              : 
    4549          528 :     free_var(&result);
    4550              : 
    4551          528 :     PG_RETURN_NUMERIC(res);
    4552              : }
    4553              : 
    4554              : 
    4555              : Datum
    4556       260345 : numeric_float8(PG_FUNCTION_ARGS)
    4557              : {
    4558       260345 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4559              :     char       *tmp;
    4560              :     Datum       result;
    4561              : 
    4562       260345 :     if (NUMERIC_IS_SPECIAL(num))
    4563              :     {
    4564           39 :         if (NUMERIC_IS_PINF(num))
    4565           12 :             PG_RETURN_FLOAT8(get_float8_infinity());
    4566           27 :         else if (NUMERIC_IS_NINF(num))
    4567           12 :             PG_RETURN_FLOAT8(-get_float8_infinity());
    4568              :         else
    4569           15 :             PG_RETURN_FLOAT8(get_float8_nan());
    4570              :     }
    4571              : 
    4572       260306 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
    4573              :                                               NumericGetDatum(num)));
    4574              : 
    4575       260306 :     result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
    4576              : 
    4577       260306 :     pfree(tmp);
    4578              : 
    4579       260306 :     PG_RETURN_DATUM(result);
    4580              : }
    4581              : 
    4582              : 
    4583              : /*
    4584              :  * Convert numeric to float8; if out of range, return +/- HUGE_VAL
    4585              :  *
    4586              :  * (internal helper function, not directly callable from SQL)
    4587              :  */
    4588              : Datum
    4589           14 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
    4590              : {
    4591           14 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4592              :     double      val;
    4593              : 
    4594           14 :     if (NUMERIC_IS_SPECIAL(num))
    4595              :     {
    4596            0 :         if (NUMERIC_IS_PINF(num))
    4597            0 :             val = HUGE_VAL;
    4598            0 :         else if (NUMERIC_IS_NINF(num))
    4599            0 :             val = -HUGE_VAL;
    4600              :         else
    4601            0 :             val = get_float8_nan();
    4602              :     }
    4603              :     else
    4604              :     {
    4605              :         NumericVar  x;
    4606              : 
    4607           14 :         init_var_from_num(num, &x);
    4608           14 :         val = numericvar_to_double_no_overflow(&x);
    4609              :     }
    4610              : 
    4611           14 :     PG_RETURN_FLOAT8(val);
    4612              : }
    4613              : 
    4614              : Datum
    4615        11308 : float4_numeric(PG_FUNCTION_ARGS)
    4616              : {
    4617        11308 :     float4      val = PG_GETARG_FLOAT4(0);
    4618              :     Numeric     res;
    4619              :     NumericVar  result;
    4620              :     char        buf[FLT_DIG + 100];
    4621              :     const char *endptr;
    4622              : 
    4623        11308 :     if (isnan(val))
    4624            3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    4625              : 
    4626        11305 :     if (isinf(val))
    4627              :     {
    4628            6 :         if (val < 0)
    4629            3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
    4630              :         else
    4631            3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
    4632              :     }
    4633              : 
    4634        11299 :     snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
    4635              : 
    4636        11299 :     init_var(&result);
    4637              : 
    4638              :     /* Assume we need not worry about leading/trailing spaces */
    4639        11299 :     (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
    4640              : 
    4641        11299 :     res = make_result(&result);
    4642              : 
    4643        11299 :     free_var(&result);
    4644              : 
    4645        11299 :     PG_RETURN_NUMERIC(res);
    4646              : }
    4647              : 
    4648              : 
    4649              : Datum
    4650         1228 : numeric_float4(PG_FUNCTION_ARGS)
    4651              : {
    4652         1228 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4653              :     char       *tmp;
    4654              :     Datum       result;
    4655              : 
    4656         1228 :     if (NUMERIC_IS_SPECIAL(num))
    4657              :     {
    4658           39 :         if (NUMERIC_IS_PINF(num))
    4659           12 :             PG_RETURN_FLOAT4(get_float4_infinity());
    4660           27 :         else if (NUMERIC_IS_NINF(num))
    4661           12 :             PG_RETURN_FLOAT4(-get_float4_infinity());
    4662              :         else
    4663           15 :             PG_RETURN_FLOAT4(get_float4_nan());
    4664              :     }
    4665              : 
    4666         1189 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
    4667              :                                               NumericGetDatum(num)));
    4668              : 
    4669         1189 :     result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
    4670              : 
    4671         1189 :     pfree(tmp);
    4672              : 
    4673         1189 :     PG_RETURN_DATUM(result);
    4674              : }
    4675              : 
    4676              : 
    4677              : Datum
    4678           62 : numeric_pg_lsn(PG_FUNCTION_ARGS)
    4679              : {
    4680           62 :     Numeric     num = PG_GETARG_NUMERIC(0);
    4681              :     NumericVar  x;
    4682              :     XLogRecPtr  result;
    4683              : 
    4684           62 :     if (NUMERIC_IS_SPECIAL(num))
    4685              :     {
    4686            3 :         if (NUMERIC_IS_NAN(num))
    4687            3 :             ereport(ERROR,
    4688              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4689              :                      errmsg("cannot convert NaN to %s", "pg_lsn")));
    4690              :         else
    4691            0 :             ereport(ERROR,
    4692              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4693              :                      errmsg("cannot convert infinity to %s", "pg_lsn")));
    4694              :     }
    4695              : 
    4696              :     /* Convert to variable format and thence to pg_lsn */
    4697           59 :     init_var_from_num(num, &x);
    4698              : 
    4699           59 :     if (!numericvar_to_uint64(&x, (uint64 *) &result))
    4700           12 :         ereport(ERROR,
    4701              :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4702              :                  errmsg("pg_lsn out of range")));
    4703              : 
    4704           47 :     PG_RETURN_LSN(result);
    4705              : }
    4706              : 
    4707              : 
    4708              : /* ----------------------------------------------------------------------
    4709              :  *
    4710              :  * Aggregate functions
    4711              :  *
    4712              :  * The transition datatype for all these aggregates is declared as INTERNAL.
    4713              :  * Actually, it's a pointer to a NumericAggState allocated in the aggregate
    4714              :  * context.  The digit buffers for the NumericVars will be there too.
    4715              :  *
    4716              :  * For integer inputs, some aggregates use special-purpose 64-bit or 128-bit
    4717              :  * integer based transition datatypes to speed up calculations.
    4718              :  *
    4719              :  * ----------------------------------------------------------------------
    4720              :  */
    4721              : 
    4722              : typedef struct NumericAggState
    4723              : {
    4724              :     bool        calcSumX2;      /* if true, calculate sumX2 */
    4725              :     MemoryContext agg_context;  /* context we're calculating in */
    4726              :     int64       N;              /* count of processed numbers */
    4727              :     NumericSumAccum sumX;       /* sum of processed numbers */
    4728              :     NumericSumAccum sumX2;      /* sum of squares of processed numbers */
    4729              :     int         maxScale;       /* maximum scale seen so far */
    4730              :     int64       maxScaleCount;  /* number of values seen with maximum scale */
    4731              :     /* These counts are *not* included in N!  Use NA_TOTAL_COUNT() as needed */
    4732              :     int64       NaNcount;       /* count of NaN values */
    4733              :     int64       pInfcount;      /* count of +Inf values */
    4734              :     int64       nInfcount;      /* count of -Inf values */
    4735              : } NumericAggState;
    4736              : 
    4737              : #define NA_TOTAL_COUNT(na) \
    4738              :     ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
    4739              : 
    4740              : /*
    4741              :  * Prepare state data for a numeric aggregate function that needs to compute
    4742              :  * sum, count and optionally sum of squares of the input.
    4743              :  */
    4744              : static NumericAggState *
    4745        85566 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
    4746              : {
    4747              :     NumericAggState *state;
    4748              :     MemoryContext agg_context;
    4749              :     MemoryContext old_context;
    4750              : 
    4751        85566 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    4752            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4753              : 
    4754        85566 :     old_context = MemoryContextSwitchTo(agg_context);
    4755              : 
    4756        85566 :     state = palloc0_object(NumericAggState);
    4757        85566 :     state->calcSumX2 = calcSumX2;
    4758        85566 :     state->agg_context = agg_context;
    4759              : 
    4760        85566 :     MemoryContextSwitchTo(old_context);
    4761              : 
    4762        85566 :     return state;
    4763              : }
    4764              : 
    4765              : /*
    4766              :  * Like makeNumericAggState(), but allocate the state in the current memory
    4767              :  * context.
    4768              :  */
    4769              : static NumericAggState *
    4770           38 : makeNumericAggStateCurrentContext(bool calcSumX2)
    4771              : {
    4772              :     NumericAggState *state;
    4773              : 
    4774           38 :     state = palloc0_object(NumericAggState);
    4775           38 :     state->calcSumX2 = calcSumX2;
    4776           38 :     state->agg_context = CurrentMemoryContext;
    4777              : 
    4778           38 :     return state;
    4779              : }
    4780              : 
    4781              : /*
    4782              :  * Accumulate a new input value for numeric aggregate functions.
    4783              :  */
    4784              : static void
    4785      1056776 : do_numeric_accum(NumericAggState *state, Numeric newval)
    4786              : {
    4787              :     NumericVar  X;
    4788              :     NumericVar  X2;
    4789              :     MemoryContext old_context;
    4790              : 
    4791              :     /* Count NaN/infinity inputs separately from all else */
    4792      1056776 :     if (NUMERIC_IS_SPECIAL(newval))
    4793              :     {
    4794           81 :         if (NUMERIC_IS_PINF(newval))
    4795           36 :             state->pInfcount++;
    4796           45 :         else if (NUMERIC_IS_NINF(newval))
    4797           18 :             state->nInfcount++;
    4798              :         else
    4799           27 :             state->NaNcount++;
    4800           81 :         return;
    4801              :     }
    4802              : 
    4803              :     /* load processed number in short-lived context */
    4804      1056695 :     init_var_from_num(newval, &X);
    4805              : 
    4806              :     /*
    4807              :      * Track the highest input dscale that we've seen, to support inverse
    4808              :      * transitions (see do_numeric_discard).
    4809              :      */
    4810      1056695 :     if (X.dscale > state->maxScale)
    4811              :     {
    4812           78 :         state->maxScale = X.dscale;
    4813           78 :         state->maxScaleCount = 1;
    4814              :     }
    4815      1056617 :     else if (X.dscale == state->maxScale)
    4816      1056599 :         state->maxScaleCount++;
    4817              : 
    4818              :     /* if we need X^2, calculate that in short-lived context */
    4819      1056695 :     if (state->calcSumX2)
    4820              :     {
    4821       120366 :         init_var(&X2);
    4822       120366 :         mul_var(&X, &X, &X2, X.dscale * 2);
    4823              :     }
    4824              : 
    4825              :     /* The rest of this needs to work in the aggregate context */
    4826      1056695 :     old_context = MemoryContextSwitchTo(state->agg_context);
    4827              : 
    4828      1056695 :     state->N++;
    4829              : 
    4830              :     /* Accumulate sums */
    4831      1056695 :     accum_sum_add(&(state->sumX), &X);
    4832              : 
    4833      1056695 :     if (state->calcSumX2)
    4834       120366 :         accum_sum_add(&(state->sumX2), &X2);
    4835              : 
    4836      1056695 :     MemoryContextSwitchTo(old_context);
    4837              : }
    4838              : 
    4839              : /*
    4840              :  * Attempt to remove an input value from the aggregated state.
    4841              :  *
    4842              :  * If the value cannot be removed then the function will return false; the
    4843              :  * possible reasons for failing are described below.
    4844              :  *
    4845              :  * If we aggregate the values 1.01 and 2 then the result will be 3.01.
    4846              :  * If we are then asked to un-aggregate the 1.01 then we must fail as we
    4847              :  * won't be able to tell what the new aggregated value's dscale should be.
    4848              :  * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
    4849              :  * have been zero if we'd really aggregated only 2.
    4850              :  *
    4851              :  * Note: alternatively, we could count the number of inputs with each possible
    4852              :  * dscale (up to some sane limit).  Not yet clear if it's worth the trouble.
    4853              :  */
    4854              : static bool
    4855          171 : do_numeric_discard(NumericAggState *state, Numeric newval)
    4856              : {
    4857              :     NumericVar  X;
    4858              :     NumericVar  X2;
    4859              :     MemoryContext old_context;
    4860              : 
    4861              :     /* Count NaN/infinity inputs separately from all else */
    4862          171 :     if (NUMERIC_IS_SPECIAL(newval))
    4863              :     {
    4864            3 :         if (NUMERIC_IS_PINF(newval))
    4865            0 :             state->pInfcount--;
    4866            3 :         else if (NUMERIC_IS_NINF(newval))
    4867            0 :             state->nInfcount--;
    4868              :         else
    4869            3 :             state->NaNcount--;
    4870            3 :         return true;
    4871              :     }
    4872              : 
    4873              :     /* load processed number in short-lived context */
    4874          168 :     init_var_from_num(newval, &X);
    4875              : 
    4876              :     /*
    4877              :      * state->sumX's dscale is the maximum dscale of any of the inputs.
    4878              :      * Removing the last input with that dscale would require us to recompute
    4879              :      * the maximum dscale of the *remaining* inputs, which we cannot do unless
    4880              :      * no more non-NaN inputs remain at all.  So we report a failure instead,
    4881              :      * and force the aggregation to be redone from scratch.
    4882              :      */
    4883          168 :     if (X.dscale == state->maxScale)
    4884              :     {
    4885          168 :         if (state->maxScaleCount > 1 || state->maxScale == 0)
    4886              :         {
    4887              :             /*
    4888              :              * Some remaining inputs have same dscale, or dscale hasn't gotten
    4889              :              * above zero anyway
    4890              :              */
    4891          159 :             state->maxScaleCount--;
    4892              :         }
    4893            9 :         else if (state->N == 1)
    4894              :         {
    4895              :             /* No remaining non-NaN inputs at all, so reset maxScale */
    4896            6 :             state->maxScale = 0;
    4897            6 :             state->maxScaleCount = 0;
    4898              :         }
    4899              :         else
    4900              :         {
    4901              :             /* Correct new maxScale is uncertain, must fail */
    4902            3 :             return false;
    4903              :         }
    4904              :     }
    4905              : 
    4906              :     /* if we need X^2, calculate that in short-lived context */
    4907          165 :     if (state->calcSumX2)
    4908              :     {
    4909          144 :         init_var(&X2);
    4910          144 :         mul_var(&X, &X, &X2, X.dscale * 2);
    4911              :     }
    4912              : 
    4913              :     /* The rest of this needs to work in the aggregate context */
    4914          165 :     old_context = MemoryContextSwitchTo(state->agg_context);
    4915              : 
    4916          165 :     if (state->N-- > 1)
    4917              :     {
    4918              :         /* Negate X, to subtract it from the sum */
    4919          156 :         X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
    4920          156 :         accum_sum_add(&(state->sumX), &X);
    4921              : 
    4922          156 :         if (state->calcSumX2)
    4923              :         {
    4924              :             /* Negate X^2. X^2 is always positive */
    4925          144 :             X2.sign = NUMERIC_NEG;
    4926          144 :             accum_sum_add(&(state->sumX2), &X2);
    4927              :         }
    4928              :     }
    4929              :     else
    4930              :     {
    4931              :         /* Zero the sums */
    4932              :         Assert(state->N == 0);
    4933              : 
    4934            9 :         accum_sum_reset(&state->sumX);
    4935            9 :         if (state->calcSumX2)
    4936            0 :             accum_sum_reset(&state->sumX2);
    4937              :     }
    4938              : 
    4939          165 :     MemoryContextSwitchTo(old_context);
    4940              : 
    4941          165 :     return true;
    4942              : }
    4943              : 
    4944              : /*
    4945              :  * Generic transition function for numeric aggregates that require sumX2.
    4946              :  */
    4947              : Datum
    4948          321 : numeric_accum(PG_FUNCTION_ARGS)
    4949              : {
    4950              :     NumericAggState *state;
    4951              : 
    4952          321 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4953              : 
    4954              :     /* Create the state data on the first call */
    4955          321 :     if (state == NULL)
    4956           87 :         state = makeNumericAggState(fcinfo, true);
    4957              : 
    4958          321 :     if (!PG_ARGISNULL(1))
    4959          312 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
    4960              : 
    4961          321 :     PG_RETURN_POINTER(state);
    4962              : }
    4963              : 
    4964              : /*
    4965              :  * Generic combine function for numeric aggregates which require sumX2
    4966              :  */
    4967              : Datum
    4968           16 : numeric_combine(PG_FUNCTION_ARGS)
    4969              : {
    4970              :     NumericAggState *state1;
    4971              :     NumericAggState *state2;
    4972              :     MemoryContext agg_context;
    4973              :     MemoryContext old_context;
    4974              : 
    4975           16 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    4976            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    4977              : 
    4978           16 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    4979           16 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
    4980              : 
    4981           16 :     if (state2 == NULL)
    4982            0 :         PG_RETURN_POINTER(state1);
    4983              : 
    4984              :     /* manually copy all fields from state2 to state1 */
    4985           16 :     if (state1 == NULL)
    4986              :     {
    4987            9 :         old_context = MemoryContextSwitchTo(agg_context);
    4988              : 
    4989            9 :         state1 = makeNumericAggStateCurrentContext(true);
    4990            9 :         state1->N = state2->N;
    4991            9 :         state1->NaNcount = state2->NaNcount;
    4992            9 :         state1->pInfcount = state2->pInfcount;
    4993            9 :         state1->nInfcount = state2->nInfcount;
    4994            9 :         state1->maxScale = state2->maxScale;
    4995            9 :         state1->maxScaleCount = state2->maxScaleCount;
    4996              : 
    4997            9 :         accum_sum_copy(&state1->sumX, &state2->sumX);
    4998            9 :         accum_sum_copy(&state1->sumX2, &state2->sumX2);
    4999              : 
    5000            9 :         MemoryContextSwitchTo(old_context);
    5001              : 
    5002            9 :         PG_RETURN_POINTER(state1);
    5003              :     }
    5004              : 
    5005            7 :     state1->N += state2->N;
    5006            7 :     state1->NaNcount += state2->NaNcount;
    5007            7 :     state1->pInfcount += state2->pInfcount;
    5008            7 :     state1->nInfcount += state2->nInfcount;
    5009              : 
    5010            7 :     if (state2->N > 0)
    5011              :     {
    5012              :         /*
    5013              :          * These are currently only needed for moving aggregates, but let's do
    5014              :          * the right thing anyway...
    5015              :          */
    5016            7 :         if (state2->maxScale > state1->maxScale)
    5017              :         {
    5018            0 :             state1->maxScale = state2->maxScale;
    5019            0 :             state1->maxScaleCount = state2->maxScaleCount;
    5020              :         }
    5021            7 :         else if (state2->maxScale == state1->maxScale)
    5022            7 :             state1->maxScaleCount += state2->maxScaleCount;
    5023              : 
    5024              :         /* The rest of this needs to work in the aggregate context */
    5025            7 :         old_context = MemoryContextSwitchTo(agg_context);
    5026              : 
    5027              :         /* Accumulate sums */
    5028            7 :         accum_sum_combine(&state1->sumX, &state2->sumX);
    5029            7 :         accum_sum_combine(&state1->sumX2, &state2->sumX2);
    5030              : 
    5031            7 :         MemoryContextSwitchTo(old_context);
    5032              :     }
    5033            7 :     PG_RETURN_POINTER(state1);
    5034              : }
    5035              : 
    5036              : /*
    5037              :  * Generic transition function for numeric aggregates that don't require sumX2.
    5038              :  */
    5039              : Datum
    5040       936404 : numeric_avg_accum(PG_FUNCTION_ARGS)
    5041              : {
    5042              :     NumericAggState *state;
    5043              : 
    5044       936404 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5045              : 
    5046              :     /* Create the state data on the first call */
    5047       936404 :     if (state == NULL)
    5048        85451 :         state = makeNumericAggState(fcinfo, false);
    5049              : 
    5050       936404 :     if (!PG_ARGISNULL(1))
    5051       936374 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
    5052              : 
    5053       936404 :     PG_RETURN_POINTER(state);
    5054              : }
    5055              : 
    5056              : /*
    5057              :  * Combine function for numeric aggregates which don't require sumX2
    5058              :  */
    5059              : Datum
    5060           10 : numeric_avg_combine(PG_FUNCTION_ARGS)
    5061              : {
    5062              :     NumericAggState *state1;
    5063              :     NumericAggState *state2;
    5064              :     MemoryContext agg_context;
    5065              :     MemoryContext old_context;
    5066              : 
    5067           10 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    5068            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5069              : 
    5070           10 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5071           10 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
    5072              : 
    5073           10 :     if (state2 == NULL)
    5074            0 :         PG_RETURN_POINTER(state1);
    5075              : 
    5076              :     /* manually copy all fields from state2 to state1 */
    5077           10 :     if (state1 == NULL)
    5078              :     {
    5079            3 :         old_context = MemoryContextSwitchTo(agg_context);
    5080              : 
    5081            3 :         state1 = makeNumericAggStateCurrentContext(false);
    5082            3 :         state1->N = state2->N;
    5083            3 :         state1->NaNcount = state2->NaNcount;
    5084            3 :         state1->pInfcount = state2->pInfcount;
    5085            3 :         state1->nInfcount = state2->nInfcount;
    5086            3 :         state1->maxScale = state2->maxScale;
    5087            3 :         state1->maxScaleCount = state2->maxScaleCount;
    5088              : 
    5089            3 :         accum_sum_copy(&state1->sumX, &state2->sumX);
    5090              : 
    5091            3 :         MemoryContextSwitchTo(old_context);
    5092              : 
    5093            3 :         PG_RETURN_POINTER(state1);
    5094              :     }
    5095              : 
    5096            7 :     state1->N += state2->N;
    5097            7 :     state1->NaNcount += state2->NaNcount;
    5098            7 :     state1->pInfcount += state2->pInfcount;
    5099            7 :     state1->nInfcount += state2->nInfcount;
    5100              : 
    5101            7 :     if (state2->N > 0)
    5102              :     {
    5103              :         /*
    5104              :          * These are currently only needed for moving aggregates, but let's do
    5105              :          * the right thing anyway...
    5106              :          */
    5107            7 :         if (state2->maxScale > state1->maxScale)
    5108              :         {
    5109            0 :             state1->maxScale = state2->maxScale;
    5110            0 :             state1->maxScaleCount = state2->maxScaleCount;
    5111              :         }
    5112            7 :         else if (state2->maxScale == state1->maxScale)
    5113            7 :             state1->maxScaleCount += state2->maxScaleCount;
    5114              : 
    5115              :         /* The rest of this needs to work in the aggregate context */
    5116            7 :         old_context = MemoryContextSwitchTo(agg_context);
    5117              : 
    5118              :         /* Accumulate sums */
    5119            7 :         accum_sum_combine(&state1->sumX, &state2->sumX);
    5120              : 
    5121            7 :         MemoryContextSwitchTo(old_context);
    5122              :     }
    5123            7 :     PG_RETURN_POINTER(state1);
    5124              : }
    5125              : 
    5126              : /*
    5127              :  * numeric_avg_serialize
    5128              :  *      Serialize NumericAggState for numeric aggregates that don't require
    5129              :  *      sumX2.
    5130              :  */
    5131              : Datum
    5132           10 : numeric_avg_serialize(PG_FUNCTION_ARGS)
    5133              : {
    5134              :     NumericAggState *state;
    5135              :     StringInfoData buf;
    5136              :     bytea      *result;
    5137              :     NumericVar  tmp_var;
    5138              : 
    5139              :     /* Ensure we disallow calling when not in aggregate context */
    5140           10 :     if (!AggCheckCallContext(fcinfo, NULL))
    5141            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5142              : 
    5143           10 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
    5144              : 
    5145           10 :     init_var(&tmp_var);
    5146              : 
    5147           10 :     pq_begintypsend(&buf);
    5148              : 
    5149              :     /* N */
    5150           10 :     pq_sendint64(&buf, state->N);
    5151              : 
    5152              :     /* sumX */
    5153           10 :     accum_sum_final(&state->sumX, &tmp_var);
    5154           10 :     numericvar_serialize(&buf, &tmp_var);
    5155              : 
    5156              :     /* maxScale */
    5157           10 :     pq_sendint32(&buf, state->maxScale);
    5158              : 
    5159              :     /* maxScaleCount */
    5160           10 :     pq_sendint64(&buf, state->maxScaleCount);
    5161              : 
    5162              :     /* NaNcount */
    5163           10 :     pq_sendint64(&buf, state->NaNcount);
    5164              : 
    5165              :     /* pInfcount */
    5166           10 :     pq_sendint64(&buf, state->pInfcount);
    5167              : 
    5168              :     /* nInfcount */
    5169           10 :     pq_sendint64(&buf, state->nInfcount);
    5170              : 
    5171           10 :     result = pq_endtypsend(&buf);
    5172              : 
    5173           10 :     free_var(&tmp_var);
    5174              : 
    5175           10 :     PG_RETURN_BYTEA_P(result);
    5176              : }
    5177              : 
    5178              : /*
    5179              :  * numeric_avg_deserialize
    5180              :  *      Deserialize bytea into NumericAggState for numeric aggregates that
    5181              :  *      don't require sumX2.
    5182              :  */
    5183              : Datum
    5184           10 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
    5185              : {
    5186              :     bytea      *sstate;
    5187              :     NumericAggState *result;
    5188              :     StringInfoData buf;
    5189              :     NumericVar  tmp_var;
    5190              : 
    5191           10 :     if (!AggCheckCallContext(fcinfo, NULL))
    5192            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5193              : 
    5194           10 :     sstate = PG_GETARG_BYTEA_PP(0);
    5195              : 
    5196           10 :     init_var(&tmp_var);
    5197              : 
    5198              :     /*
    5199              :      * Initialize a StringInfo so that we can "receive" it using the standard
    5200              :      * recv-function infrastructure.
    5201              :      */
    5202           10 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
    5203           10 :                            VARSIZE_ANY_EXHDR(sstate));
    5204              : 
    5205           10 :     result = makeNumericAggStateCurrentContext(false);
    5206              : 
    5207              :     /* N */
    5208           10 :     result->N = pq_getmsgint64(&buf);
    5209              : 
    5210              :     /* sumX */
    5211           10 :     numericvar_deserialize(&buf, &tmp_var);
    5212           10 :     accum_sum_add(&(result->sumX), &tmp_var);
    5213              : 
    5214              :     /* maxScale */
    5215           10 :     result->maxScale = pq_getmsgint(&buf, 4);
    5216              : 
    5217              :     /* maxScaleCount */
    5218           10 :     result->maxScaleCount = pq_getmsgint64(&buf);
    5219              : 
    5220              :     /* NaNcount */
    5221           10 :     result->NaNcount = pq_getmsgint64(&buf);
    5222              : 
    5223              :     /* pInfcount */
    5224           10 :     result->pInfcount = pq_getmsgint64(&buf);
    5225              : 
    5226              :     /* nInfcount */
    5227           10 :     result->nInfcount = pq_getmsgint64(&buf);
    5228              : 
    5229           10 :     pq_getmsgend(&buf);
    5230              : 
    5231           10 :     free_var(&tmp_var);
    5232              : 
    5233           10 :     PG_RETURN_POINTER(result);
    5234              : }
    5235              : 
    5236              : /*
    5237              :  * numeric_serialize
    5238              :  *      Serialization function for NumericAggState for numeric aggregates that
    5239              :  *      require sumX2.
    5240              :  */
    5241              : Datum
    5242           16 : numeric_serialize(PG_FUNCTION_ARGS)
    5243              : {
    5244              :     NumericAggState *state;
    5245              :     StringInfoData buf;
    5246              :     bytea      *result;
    5247              :     NumericVar  tmp_var;
    5248              : 
    5249              :     /* Ensure we disallow calling when not in aggregate context */
    5250           16 :     if (!AggCheckCallContext(fcinfo, NULL))
    5251            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5252              : 
    5253           16 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
    5254              : 
    5255           16 :     init_var(&tmp_var);
    5256              : 
    5257           16 :     pq_begintypsend(&buf);
    5258              : 
    5259              :     /* N */
    5260           16 :     pq_sendint64(&buf, state->N);
    5261              : 
    5262              :     /* sumX */
    5263           16 :     accum_sum_final(&state->sumX, &tmp_var);
    5264           16 :     numericvar_serialize(&buf, &tmp_var);
    5265              : 
    5266              :     /* sumX2 */
    5267           16 :     accum_sum_final(&state->sumX2, &tmp_var);
    5268           16 :     numericvar_serialize(&buf, &tmp_var);
    5269              : 
    5270              :     /* maxScale */
    5271           16 :     pq_sendint32(&buf, state->maxScale);
    5272              : 
    5273              :     /* maxScaleCount */
    5274           16 :     pq_sendint64(&buf, state->maxScaleCount);
    5275              : 
    5276              :     /* NaNcount */
    5277           16 :     pq_sendint64(&buf, state->NaNcount);
    5278              : 
    5279              :     /* pInfcount */
    5280           16 :     pq_sendint64(&buf, state->pInfcount);
    5281              : 
    5282              :     /* nInfcount */
    5283           16 :     pq_sendint64(&buf, state->nInfcount);
    5284              : 
    5285           16 :     result = pq_endtypsend(&buf);
    5286              : 
    5287           16 :     free_var(&tmp_var);
    5288              : 
    5289           16 :     PG_RETURN_BYTEA_P(result);
    5290              : }
    5291              : 
    5292              : /*
    5293              :  * numeric_deserialize
    5294              :  *      Deserialization function for NumericAggState for numeric aggregates that
    5295              :  *      require sumX2.
    5296              :  */
    5297              : Datum
    5298           16 : numeric_deserialize(PG_FUNCTION_ARGS)
    5299              : {
    5300              :     bytea      *sstate;
    5301              :     NumericAggState *result;
    5302              :     StringInfoData buf;
    5303              :     NumericVar  tmp_var;
    5304              : 
    5305           16 :     if (!AggCheckCallContext(fcinfo, NULL))
    5306            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5307              : 
    5308           16 :     sstate = PG_GETARG_BYTEA_PP(0);
    5309              : 
    5310           16 :     init_var(&tmp_var);
    5311              : 
    5312              :     /*
    5313              :      * Initialize a StringInfo so that we can "receive" it using the standard
    5314              :      * recv-function infrastructure.
    5315              :      */
    5316           16 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
    5317           16 :                            VARSIZE_ANY_EXHDR(sstate));
    5318              : 
    5319           16 :     result = makeNumericAggStateCurrentContext(false);
    5320              : 
    5321              :     /* N */
    5322           16 :     result->N = pq_getmsgint64(&buf);
    5323              : 
    5324              :     /* sumX */
    5325           16 :     numericvar_deserialize(&buf, &tmp_var);
    5326           16 :     accum_sum_add(&(result->sumX), &tmp_var);
    5327              : 
    5328              :     /* sumX2 */
    5329           16 :     numericvar_deserialize(&buf, &tmp_var);
    5330           16 :     accum_sum_add(&(result->sumX2), &tmp_var);
    5331              : 
    5332              :     /* maxScale */
    5333           16 :     result->maxScale = pq_getmsgint(&buf, 4);
    5334              : 
    5335              :     /* maxScaleCount */
    5336           16 :     result->maxScaleCount = pq_getmsgint64(&buf);
    5337              : 
    5338              :     /* NaNcount */
    5339           16 :     result->NaNcount = pq_getmsgint64(&buf);
    5340              : 
    5341              :     /* pInfcount */
    5342           16 :     result->pInfcount = pq_getmsgint64(&buf);
    5343              : 
    5344              :     /* nInfcount */
    5345           16 :     result->nInfcount = pq_getmsgint64(&buf);
    5346              : 
    5347           16 :     pq_getmsgend(&buf);
    5348              : 
    5349           16 :     free_var(&tmp_var);
    5350              : 
    5351           16 :     PG_RETURN_POINTER(result);
    5352              : }
    5353              : 
    5354              : /*
    5355              :  * Generic inverse transition function for numeric aggregates
    5356              :  * (with or without requirement for X^2).
    5357              :  */
    5358              : Datum
    5359          114 : numeric_accum_inv(PG_FUNCTION_ARGS)
    5360              : {
    5361              :     NumericAggState *state;
    5362              : 
    5363          114 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5364              : 
    5365              :     /* Should not get here with no state */
    5366          114 :     if (state == NULL)
    5367            0 :         elog(ERROR, "numeric_accum_inv called with NULL state");
    5368              : 
    5369          114 :     if (!PG_ARGISNULL(1))
    5370              :     {
    5371              :         /* If we fail to perform the inverse transition, return NULL */
    5372           99 :         if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
    5373            3 :             PG_RETURN_NULL();
    5374              :     }
    5375              : 
    5376          111 :     PG_RETURN_POINTER(state);
    5377              : }
    5378              : 
    5379              : 
    5380              : /*
    5381              :  * Integer data types in general use Numeric accumulators to share code and
    5382              :  * avoid risk of overflow.  However for performance reasons optimized
    5383              :  * special-purpose accumulator routines are used when possible:
    5384              :  *
    5385              :  * For 16-bit and 32-bit inputs, N and sum(X) fit into 64-bit, so 64-bit
    5386              :  * accumulators are used for SUM and AVG of these data types.
    5387              :  *
    5388              :  * For 16-bit and 32-bit inputs, sum(X^2) fits into 128-bit, so 128-bit
    5389              :  * accumulators are used for STDDEV_POP, STDDEV_SAMP, VAR_POP, and VAR_SAMP of
    5390              :  * these data types.
    5391              :  *
    5392              :  * For 64-bit inputs, sum(X) fits into 128-bit, so a 128-bit accumulator is
    5393              :  * used for SUM(int8) and AVG(int8).
    5394              :  */
    5395              : 
    5396              : typedef struct Int128AggState
    5397              : {
    5398              :     bool        calcSumX2;      /* if true, calculate sumX2 */
    5399              :     int64       N;              /* count of processed numbers */
    5400              :     INT128      sumX;           /* sum of processed numbers */
    5401              :     INT128      sumX2;          /* sum of squares of processed numbers */
    5402              : } Int128AggState;
    5403              : 
    5404              : /*
    5405              :  * Prepare state data for a 128-bit aggregate function that needs to compute
    5406              :  * sum, count and optionally sum of squares of the input.
    5407              :  */
    5408              : static Int128AggState *
    5409          482 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
    5410              : {
    5411              :     Int128AggState *state;
    5412              :     MemoryContext agg_context;
    5413              :     MemoryContext old_context;
    5414              : 
    5415          482 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    5416            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5417              : 
    5418          482 :     old_context = MemoryContextSwitchTo(agg_context);
    5419              : 
    5420          482 :     state = palloc0_object(Int128AggState);
    5421          482 :     state->calcSumX2 = calcSumX2;
    5422              : 
    5423          482 :     MemoryContextSwitchTo(old_context);
    5424              : 
    5425          482 :     return state;
    5426              : }
    5427              : 
    5428              : /*
    5429              :  * Like makeInt128AggState(), but allocate the state in the current memory
    5430              :  * context.
    5431              :  */
    5432              : static Int128AggState *
    5433           25 : makeInt128AggStateCurrentContext(bool calcSumX2)
    5434              : {
    5435              :     Int128AggState *state;
    5436              : 
    5437           25 :     state = palloc0_object(Int128AggState);
    5438           25 :     state->calcSumX2 = calcSumX2;
    5439              : 
    5440           25 :     return state;
    5441              : }
    5442              : 
    5443              : /*
    5444              :  * Accumulate a new input value for 128-bit aggregate functions.
    5445              :  */
    5446              : static void
    5447       278739 : do_int128_accum(Int128AggState *state, int64 newval)
    5448              : {
    5449       278739 :     if (state->calcSumX2)
    5450       121180 :         int128_add_int64_mul_int64(&state->sumX2, newval, newval);
    5451              : 
    5452       278739 :     int128_add_int64(&state->sumX, newval);
    5453       278739 :     state->N++;
    5454       278739 : }
    5455              : 
    5456              : /*
    5457              :  * Remove an input value from the aggregated state.
    5458              :  */
    5459              : static void
    5460          156 : do_int128_discard(Int128AggState *state, int64 newval)
    5461              : {
    5462          156 :     if (state->calcSumX2)
    5463          144 :         int128_sub_int64_mul_int64(&state->sumX2, newval, newval);
    5464              : 
    5465          156 :     int128_sub_int64(&state->sumX, newval);
    5466          156 :     state->N--;
    5467          156 : }
    5468              : 
    5469              : Datum
    5470           99 : int2_accum(PG_FUNCTION_ARGS)
    5471              : {
    5472              :     Int128AggState *state;
    5473              : 
    5474           99 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5475              : 
    5476              :     /* Create the state data on the first call */
    5477           99 :     if (state == NULL)
    5478           18 :         state = makeInt128AggState(fcinfo, true);
    5479              : 
    5480           99 :     if (!PG_ARGISNULL(1))
    5481           90 :         do_int128_accum(state, PG_GETARG_INT16(1));
    5482              : 
    5483           99 :     PG_RETURN_POINTER(state);
    5484              : }
    5485              : 
    5486              : Datum
    5487       121099 : int4_accum(PG_FUNCTION_ARGS)
    5488              : {
    5489              :     Int128AggState *state;
    5490              : 
    5491       121099 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5492              : 
    5493              :     /* Create the state data on the first call */
    5494       121099 :     if (state == NULL)
    5495           39 :         state = makeInt128AggState(fcinfo, true);
    5496              : 
    5497       121099 :     if (!PG_ARGISNULL(1))
    5498       121090 :         do_int128_accum(state, PG_GETARG_INT32(1));
    5499              : 
    5500       121099 :     PG_RETURN_POINTER(state);
    5501              : }
    5502              : 
    5503              : Datum
    5504       120099 : int8_accum(PG_FUNCTION_ARGS)
    5505              : {
    5506              :     NumericAggState *state;
    5507              : 
    5508       120099 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5509              : 
    5510              :     /* Create the state data on the first call */
    5511       120099 :     if (state == NULL)
    5512           28 :         state = makeNumericAggState(fcinfo, true);
    5513              : 
    5514       120099 :     if (!PG_ARGISNULL(1))
    5515       120090 :         do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
    5516              : 
    5517       120099 :     PG_RETURN_POINTER(state);
    5518              : }
    5519              : 
    5520              : /*
    5521              :  * Combine function for Int128AggState for aggregates which require sumX2
    5522              :  */
    5523              : Datum
    5524           11 : numeric_poly_combine(PG_FUNCTION_ARGS)
    5525              : {
    5526              :     Int128AggState *state1;
    5527              :     Int128AggState *state2;
    5528              :     MemoryContext agg_context;
    5529              :     MemoryContext old_context;
    5530              : 
    5531           11 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    5532            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5533              : 
    5534           11 :     state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5535           11 :     state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
    5536              : 
    5537           11 :     if (state2 == NULL)
    5538            0 :         PG_RETURN_POINTER(state1);
    5539              : 
    5540              :     /* manually copy all fields from state2 to state1 */
    5541           11 :     if (state1 == NULL)
    5542              :     {
    5543            3 :         old_context = MemoryContextSwitchTo(agg_context);
    5544              : 
    5545            3 :         state1 = makeInt128AggState(fcinfo, true);
    5546            3 :         state1->N = state2->N;
    5547            3 :         state1->sumX = state2->sumX;
    5548            3 :         state1->sumX2 = state2->sumX2;
    5549              : 
    5550            3 :         MemoryContextSwitchTo(old_context);
    5551              : 
    5552            3 :         PG_RETURN_POINTER(state1);
    5553              :     }
    5554              : 
    5555            8 :     if (state2->N > 0)
    5556              :     {
    5557            8 :         state1->N += state2->N;
    5558            8 :         int128_add_int128(&state1->sumX, state2->sumX);
    5559            8 :         int128_add_int128(&state1->sumX2, state2->sumX2);
    5560              :     }
    5561            8 :     PG_RETURN_POINTER(state1);
    5562              : }
    5563              : 
    5564              : /*
    5565              :  * int128_serialize - serialize a 128-bit integer to binary format
    5566              :  */
    5567              : static inline void
    5568           36 : int128_serialize(StringInfo buf, INT128 val)
    5569              : {
    5570           36 :     pq_sendint64(buf, PG_INT128_HI_INT64(val));
    5571           36 :     pq_sendint64(buf, PG_INT128_LO_UINT64(val));
    5572           36 : }
    5573              : 
    5574              : /*
    5575              :  * int128_deserialize - deserialize binary format to a 128-bit integer.
    5576              :  */
    5577              : static inline INT128
    5578           36 : int128_deserialize(StringInfo buf)
    5579              : {
    5580           36 :     int64       hi = pq_getmsgint64(buf);
    5581           36 :     uint64      lo = pq_getmsgint64(buf);
    5582              : 
    5583           36 :     return make_int128(hi, lo);
    5584              : }
    5585              : 
    5586              : /*
    5587              :  * numeric_poly_serialize
    5588              :  *      Serialize Int128AggState into bytea for aggregate functions which
    5589              :  *      require sumX2.
    5590              :  */
    5591              : Datum
    5592           11 : numeric_poly_serialize(PG_FUNCTION_ARGS)
    5593              : {
    5594              :     Int128AggState *state;
    5595              :     StringInfoData buf;
    5596              :     bytea      *result;
    5597              : 
    5598              :     /* Ensure we disallow calling when not in aggregate context */
    5599           11 :     if (!AggCheckCallContext(fcinfo, NULL))
    5600            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5601              : 
    5602           11 :     state = (Int128AggState *) PG_GETARG_POINTER(0);
    5603              : 
    5604           11 :     pq_begintypsend(&buf);
    5605              : 
    5606              :     /* N */
    5607           11 :     pq_sendint64(&buf, state->N);
    5608              : 
    5609              :     /* sumX */
    5610           11 :     int128_serialize(&buf, state->sumX);
    5611              : 
    5612              :     /* sumX2 */
    5613           11 :     int128_serialize(&buf, state->sumX2);
    5614              : 
    5615           11 :     result = pq_endtypsend(&buf);
    5616              : 
    5617           11 :     PG_RETURN_BYTEA_P(result);
    5618              : }
    5619              : 
    5620              : /*
    5621              :  * numeric_poly_deserialize
    5622              :  *      Deserialize Int128AggState from bytea for aggregate functions which
    5623              :  *      require sumX2.
    5624              :  */
    5625              : Datum
    5626           11 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
    5627              : {
    5628              :     bytea      *sstate;
    5629              :     Int128AggState *result;
    5630              :     StringInfoData buf;
    5631              : 
    5632           11 :     if (!AggCheckCallContext(fcinfo, NULL))
    5633            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5634              : 
    5635           11 :     sstate = PG_GETARG_BYTEA_PP(0);
    5636              : 
    5637              :     /*
    5638              :      * Initialize a StringInfo so that we can "receive" it using the standard
    5639              :      * recv-function infrastructure.
    5640              :      */
    5641           11 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
    5642           11 :                            VARSIZE_ANY_EXHDR(sstate));
    5643              : 
    5644           11 :     result = makeInt128AggStateCurrentContext(false);
    5645              : 
    5646              :     /* N */
    5647           11 :     result->N = pq_getmsgint64(&buf);
    5648              : 
    5649              :     /* sumX */
    5650           11 :     result->sumX = int128_deserialize(&buf);
    5651              : 
    5652              :     /* sumX2 */
    5653           11 :     result->sumX2 = int128_deserialize(&buf);
    5654              : 
    5655           11 :     pq_getmsgend(&buf);
    5656              : 
    5657           11 :     PG_RETURN_POINTER(result);
    5658              : }
    5659              : 
    5660              : /*
    5661              :  * Transition function for int8 input when we don't need sumX2.
    5662              :  */
    5663              : Datum
    5664       159458 : int8_avg_accum(PG_FUNCTION_ARGS)
    5665              : {
    5666              :     Int128AggState *state;
    5667              : 
    5668       159458 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5669              : 
    5670              :     /* Create the state data on the first call */
    5671       159458 :     if (state == NULL)
    5672          416 :         state = makeInt128AggState(fcinfo, false);
    5673              : 
    5674       159458 :     if (!PG_ARGISNULL(1))
    5675       157559 :         do_int128_accum(state, PG_GETARG_INT64(1));
    5676              : 
    5677       159458 :     PG_RETURN_POINTER(state);
    5678              : }
    5679              : 
    5680              : /*
    5681              :  * Combine function for Int128AggState for aggregates which don't require
    5682              :  * sumX2
    5683              :  */
    5684              : Datum
    5685           14 : int8_avg_combine(PG_FUNCTION_ARGS)
    5686              : {
    5687              :     Int128AggState *state1;
    5688              :     Int128AggState *state2;
    5689              :     MemoryContext agg_context;
    5690              :     MemoryContext old_context;
    5691              : 
    5692           14 :     if (!AggCheckCallContext(fcinfo, &agg_context))
    5693            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5694              : 
    5695           14 :     state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5696           14 :     state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
    5697              : 
    5698           14 :     if (state2 == NULL)
    5699            0 :         PG_RETURN_POINTER(state1);
    5700              : 
    5701              :     /* manually copy all fields from state2 to state1 */
    5702           14 :     if (state1 == NULL)
    5703              :     {
    5704            6 :         old_context = MemoryContextSwitchTo(agg_context);
    5705              : 
    5706            6 :         state1 = makeInt128AggState(fcinfo, false);
    5707            6 :         state1->N = state2->N;
    5708            6 :         state1->sumX = state2->sumX;
    5709              : 
    5710            6 :         MemoryContextSwitchTo(old_context);
    5711              : 
    5712            6 :         PG_RETURN_POINTER(state1);
    5713              :     }
    5714              : 
    5715            8 :     if (state2->N > 0)
    5716              :     {
    5717            8 :         state1->N += state2->N;
    5718            8 :         int128_add_int128(&state1->sumX, state2->sumX);
    5719              :     }
    5720            8 :     PG_RETURN_POINTER(state1);
    5721              : }
    5722              : 
    5723              : /*
    5724              :  * int8_avg_serialize
    5725              :  *      Serialize Int128AggState into bytea for aggregate functions which
    5726              :  *      don't require sumX2.
    5727              :  */
    5728              : Datum
    5729           14 : int8_avg_serialize(PG_FUNCTION_ARGS)
    5730              : {
    5731              :     Int128AggState *state;
    5732              :     StringInfoData buf;
    5733              :     bytea      *result;
    5734              : 
    5735              :     /* Ensure we disallow calling when not in aggregate context */
    5736           14 :     if (!AggCheckCallContext(fcinfo, NULL))
    5737            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5738              : 
    5739           14 :     state = (Int128AggState *) PG_GETARG_POINTER(0);
    5740              : 
    5741           14 :     pq_begintypsend(&buf);
    5742              : 
    5743              :     /* N */
    5744           14 :     pq_sendint64(&buf, state->N);
    5745              : 
    5746              :     /* sumX */
    5747           14 :     int128_serialize(&buf, state->sumX);
    5748              : 
    5749           14 :     result = pq_endtypsend(&buf);
    5750              : 
    5751           14 :     PG_RETURN_BYTEA_P(result);
    5752              : }
    5753              : 
    5754              : /*
    5755              :  * int8_avg_deserialize
    5756              :  *      Deserialize Int128AggState from bytea for aggregate functions which
    5757              :  *      don't require sumX2.
    5758              :  */
    5759              : Datum
    5760           14 : int8_avg_deserialize(PG_FUNCTION_ARGS)
    5761              : {
    5762              :     bytea      *sstate;
    5763              :     Int128AggState *result;
    5764              :     StringInfoData buf;
    5765              : 
    5766           14 :     if (!AggCheckCallContext(fcinfo, NULL))
    5767            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    5768              : 
    5769           14 :     sstate = PG_GETARG_BYTEA_PP(0);
    5770              : 
    5771              :     /*
    5772              :      * Initialize a StringInfo so that we can "receive" it using the standard
    5773              :      * recv-function infrastructure.
    5774              :      */
    5775           14 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
    5776           14 :                            VARSIZE_ANY_EXHDR(sstate));
    5777              : 
    5778           14 :     result = makeInt128AggStateCurrentContext(false);
    5779              : 
    5780              :     /* N */
    5781           14 :     result->N = pq_getmsgint64(&buf);
    5782              : 
    5783              :     /* sumX */
    5784           14 :     result->sumX = int128_deserialize(&buf);
    5785              : 
    5786           14 :     pq_getmsgend(&buf);
    5787              : 
    5788           14 :     PG_RETURN_POINTER(result);
    5789              : }
    5790              : 
    5791              : /*
    5792              :  * Inverse transition functions to go with the above.
    5793              :  */
    5794              : 
    5795              : Datum
    5796           81 : int2_accum_inv(PG_FUNCTION_ARGS)
    5797              : {
    5798              :     Int128AggState *state;
    5799              : 
    5800           81 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5801              : 
    5802              :     /* Should not get here with no state */
    5803           81 :     if (state == NULL)
    5804            0 :         elog(ERROR, "int2_accum_inv called with NULL state");
    5805              : 
    5806           81 :     if (!PG_ARGISNULL(1))
    5807           72 :         do_int128_discard(state, PG_GETARG_INT16(1));
    5808              : 
    5809           81 :     PG_RETURN_POINTER(state);
    5810              : }
    5811              : 
    5812              : Datum
    5813           81 : int4_accum_inv(PG_FUNCTION_ARGS)
    5814              : {
    5815              :     Int128AggState *state;
    5816              : 
    5817           81 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5818              : 
    5819              :     /* Should not get here with no state */
    5820           81 :     if (state == NULL)
    5821            0 :         elog(ERROR, "int4_accum_inv called with NULL state");
    5822              : 
    5823           81 :     if (!PG_ARGISNULL(1))
    5824           72 :         do_int128_discard(state, PG_GETARG_INT32(1));
    5825              : 
    5826           81 :     PG_RETURN_POINTER(state);
    5827              : }
    5828              : 
    5829              : Datum
    5830           81 : int8_accum_inv(PG_FUNCTION_ARGS)
    5831              : {
    5832              :     NumericAggState *state;
    5833              : 
    5834           81 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5835              : 
    5836              :     /* Should not get here with no state */
    5837           81 :     if (state == NULL)
    5838            0 :         elog(ERROR, "int8_accum_inv called with NULL state");
    5839              : 
    5840           81 :     if (!PG_ARGISNULL(1))
    5841              :     {
    5842              :         /* Should never fail, all inputs have dscale 0 */
    5843           72 :         if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
    5844            0 :             elog(ERROR, "do_numeric_discard failed unexpectedly");
    5845              :     }
    5846              : 
    5847           81 :     PG_RETURN_POINTER(state);
    5848              : }
    5849              : 
    5850              : Datum
    5851           18 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
    5852              : {
    5853              :     Int128AggState *state;
    5854              : 
    5855           18 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5856              : 
    5857              :     /* Should not get here with no state */
    5858           18 :     if (state == NULL)
    5859            0 :         elog(ERROR, "int8_avg_accum_inv called with NULL state");
    5860              : 
    5861           18 :     if (!PG_ARGISNULL(1))
    5862           12 :         do_int128_discard(state, PG_GETARG_INT64(1));
    5863              : 
    5864           18 :     PG_RETURN_POINTER(state);
    5865              : }
    5866              : 
    5867              : Datum
    5868          525 : numeric_poly_sum(PG_FUNCTION_ARGS)
    5869              : {
    5870              :     Int128AggState *state;
    5871              :     Numeric     res;
    5872              :     NumericVar  result;
    5873              : 
    5874          525 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5875              : 
    5876              :     /* If there were no non-null inputs, return NULL */
    5877          525 :     if (state == NULL || state->N == 0)
    5878           12 :         PG_RETURN_NULL();
    5879              : 
    5880          513 :     init_var(&result);
    5881              : 
    5882          513 :     int128_to_numericvar(state->sumX, &result);
    5883              : 
    5884          513 :     res = make_result(&result);
    5885              : 
    5886          513 :     free_var(&result);
    5887              : 
    5888          513 :     PG_RETURN_NUMERIC(res);
    5889              : }
    5890              : 
    5891              : Datum
    5892           18 : numeric_poly_avg(PG_FUNCTION_ARGS)
    5893              : {
    5894              :     Int128AggState *state;
    5895              :     NumericVar  result;
    5896              :     Datum       countd,
    5897              :                 sumd;
    5898              : 
    5899           18 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    5900              : 
    5901              :     /* If there were no non-null inputs, return NULL */
    5902           18 :     if (state == NULL || state->N == 0)
    5903            9 :         PG_RETURN_NULL();
    5904              : 
    5905            9 :     init_var(&result);
    5906              : 
    5907            9 :     int128_to_numericvar(state->sumX, &result);
    5908              : 
    5909            9 :     countd = NumericGetDatum(int64_to_numeric(state->N));
    5910            9 :     sumd = NumericGetDatum(make_result(&result));
    5911              : 
    5912            9 :     free_var(&result);
    5913              : 
    5914            9 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
    5915              : }
    5916              : 
    5917              : Datum
    5918           39 : numeric_avg(PG_FUNCTION_ARGS)
    5919              : {
    5920              :     NumericAggState *state;
    5921              :     Datum       N_datum;
    5922              :     Datum       sumX_datum;
    5923              :     NumericVar  sumX_var;
    5924              : 
    5925           39 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5926              : 
    5927              :     /* If there were no non-null inputs, return NULL */
    5928           39 :     if (state == NULL || NA_TOTAL_COUNT(state) == 0)
    5929            9 :         PG_RETURN_NULL();
    5930              : 
    5931           30 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
    5932            3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    5933              : 
    5934              :     /* adding plus and minus infinities gives NaN */
    5935           27 :     if (state->pInfcount > 0 && state->nInfcount > 0)
    5936            3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    5937           24 :     if (state->pInfcount > 0)
    5938            9 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
    5939           15 :     if (state->nInfcount > 0)
    5940            3 :         PG_RETURN_NUMERIC(make_result(&const_ninf));
    5941              : 
    5942           12 :     N_datum = NumericGetDatum(int64_to_numeric(state->N));
    5943              : 
    5944           12 :     init_var(&sumX_var);
    5945           12 :     accum_sum_final(&state->sumX, &sumX_var);
    5946           12 :     sumX_datum = NumericGetDatum(make_result(&sumX_var));
    5947           12 :     free_var(&sumX_var);
    5948              : 
    5949           12 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
    5950              : }
    5951              : 
    5952              : Datum
    5953        85453 : numeric_sum(PG_FUNCTION_ARGS)
    5954              : {
    5955              :     NumericAggState *state;
    5956              :     NumericVar  sumX_var;
    5957              :     Numeric     result;
    5958              : 
    5959        85453 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    5960              : 
    5961              :     /* If there were no non-null inputs, return NULL */
    5962        85453 :     if (state == NULL || NA_TOTAL_COUNT(state) == 0)
    5963            9 :         PG_RETURN_NULL();
    5964              : 
    5965        85444 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
    5966            9 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    5967              : 
    5968              :     /* adding plus and minus infinities gives NaN */
    5969        85435 :     if (state->pInfcount > 0 && state->nInfcount > 0)
    5970            3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
    5971        85432 :     if (state->pInfcount > 0)
    5972            9 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
    5973        85423 :     if (state->nInfcount > 0)
    5974            3 :         PG_RETURN_NUMERIC(make_result(&const_ninf));
    5975              : 
    5976        85420 :     init_var(&sumX_var);
    5977        85420 :     accum_sum_final(&state->sumX, &sumX_var);
    5978        85420 :     result = make_result(&sumX_var);
    5979        85420 :     free_var(&sumX_var);
    5980              : 
    5981        85420 :     PG_RETURN_NUMERIC(result);
    5982              : }
    5983              : 
    5984              : /*
    5985              :  * Workhorse routine for the standard deviance and variance
    5986              :  * aggregates. 'state' is aggregate's transition state.
    5987              :  * 'variance' specifies whether we should calculate the
    5988              :  * variance or the standard deviation. 'sample' indicates whether the
    5989              :  * caller is interested in the sample or the population
    5990              :  * variance/stddev.
    5991              :  *
    5992              :  * If appropriate variance statistic is undefined for the input,
    5993              :  * *is_null is set to true and NULL is returned.
    5994              :  */
    5995              : static Numeric
    5996          493 : numeric_stddev_internal(NumericAggState *state,
    5997              :                         bool variance, bool sample,
    5998              :                         bool *is_null)
    5999              : {
    6000              :     Numeric     res;
    6001              :     NumericVar  vN,
    6002              :                 vsumX,
    6003              :                 vsumX2,
    6004              :                 vNminus1;
    6005              :     int64       totCount;
    6006              :     int         rscale;
    6007              : 
    6008              :     /*
    6009              :      * Sample stddev and variance are undefined when N <= 1; population stddev
    6010              :      * is undefined when N == 0.  Return NULL in either case (note that NaNs
    6011              :      * and infinities count as normal inputs for this purpose).
    6012              :      */
    6013          493 :     if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
    6014              :     {
    6015            0 :         *is_null = true;
    6016            0 :         return NULL;
    6017              :     }
    6018              : 
    6019          493 :     if (sample && totCount <= 1)
    6020              :     {
    6021           66 :         *is_null = true;
    6022           66 :         return NULL;
    6023              :     }
    6024              : 
    6025          427 :     *is_null = false;
    6026              : 
    6027              :     /*
    6028              :      * Deal with NaN and infinity cases.  By analogy to the behavior of the
    6029              :      * float8 functions, any infinity input produces NaN output.
    6030              :      */
    6031          427 :     if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
    6032           27 :         return make_result(&const_nan);
    6033              : 
    6034              :     /* OK, normal calculation applies */
    6035          400 :     init_var(&vN);
    6036          400 :     init_var(&vsumX);
    6037          400 :     init_var(&vsumX2);
    6038              : 
    6039          400 :     int64_to_numericvar(state->N, &vN);
    6040          400 :     accum_sum_final(&(state->sumX), &vsumX);
    6041          400 :     accum_sum_final(&(state->sumX2), &vsumX2);
    6042              : 
    6043          400 :     init_var(&vNminus1);
    6044          400 :     sub_var(&vN, &const_one, &vNminus1);
    6045              : 
    6046              :     /* compute rscale for mul_var calls */
    6047          400 :     rscale = vsumX.dscale * 2;
    6048              : 
    6049          400 :     mul_var(&vsumX, &vsumX, &vsumX, rscale);    /* vsumX = sumX * sumX */
    6050          400 :     mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
    6051          400 :     sub_var(&vsumX2, &vsumX, &vsumX2);  /* N * sumX2 - sumX * sumX */
    6052              : 
    6053          400 :     if (cmp_var(&vsumX2, &const_zero) <= 0)
    6054              :     {
    6055              :         /* Watch out for roundoff error producing a negative numerator */
    6056           40 :         res = make_result(&const_zero);
    6057              :     }
    6058              :     else
    6059              :     {
    6060          360 :         if (sample)
    6061          246 :             mul_var(&vN, &vNminus1, &vNminus1, 0);  /* N * (N - 1) */
    6062              :         else
    6063          114 :             mul_var(&vN, &vN, &vNminus1, 0);    /* N * N */
    6064          360 :         rscale = select_div_scale(&vsumX2, &vNminus1);
    6065          360 :         div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true);    /* variance */
    6066          360 :         if (!variance)
    6067          189 :             sqrt_var(&vsumX, &vsumX, rscale);   /* stddev */
    6068              : 
    6069          360 :         res = make_result(&vsumX);
    6070              :     }
    6071              : 
    6072          400 :     free_var(&vNminus1);
    6073          400 :     free_var(&vsumX);
    6074          400 :     free_var(&vsumX2);
    6075              : 
    6076          400 :     return res;
    6077              : }
    6078              : 
    6079              : Datum
    6080           90 : numeric_var_samp(PG_FUNCTION_ARGS)
    6081              : {
    6082              :     NumericAggState *state;
    6083              :     Numeric     res;
    6084              :     bool        is_null;
    6085              : 
    6086           90 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    6087              : 
    6088           90 :     res = numeric_stddev_internal(state, true, true, &is_null);
    6089              : 
    6090           90 :     if (is_null)
    6091           21 :         PG_RETURN_NULL();
    6092              :     else
    6093           69 :         PG_RETURN_NUMERIC(res);
    6094              : }
    6095              : 
    6096              : Datum
    6097           87 : numeric_stddev_samp(PG_FUNCTION_ARGS)
    6098              : {
    6099              :     NumericAggState *state;
    6100              :     Numeric     res;
    6101              :     bool        is_null;
    6102              : 
    6103           87 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    6104              : 
    6105           87 :     res = numeric_stddev_internal(state, false, true, &is_null);
    6106              : 
    6107           87 :     if (is_null)
    6108           21 :         PG_RETURN_NULL();
    6109              :     else
    6110           66 :         PG_RETURN_NUMERIC(res);
    6111              : }
    6112              : 
    6113              : Datum
    6114           57 : numeric_var_pop(PG_FUNCTION_ARGS)
    6115              : {
    6116              :     NumericAggState *state;
    6117              :     Numeric     res;
    6118              :     bool        is_null;
    6119              : 
    6120           57 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    6121              : 
    6122           57 :     res = numeric_stddev_internal(state, true, false, &is_null);
    6123              : 
    6124           57 :     if (is_null)
    6125            0 :         PG_RETURN_NULL();
    6126              :     else
    6127           57 :         PG_RETURN_NUMERIC(res);
    6128              : }
    6129              : 
    6130              : Datum
    6131           48 : numeric_stddev_pop(PG_FUNCTION_ARGS)
    6132              : {
    6133              :     NumericAggState *state;
    6134              :     Numeric     res;
    6135              :     bool        is_null;
    6136              : 
    6137           48 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
    6138              : 
    6139           48 :     res = numeric_stddev_internal(state, false, false, &is_null);
    6140              : 
    6141           48 :     if (is_null)
    6142            0 :         PG_RETURN_NULL();
    6143              :     else
    6144           48 :         PG_RETURN_NUMERIC(res);
    6145              : }
    6146              : 
    6147              : static Numeric
    6148          211 : numeric_poly_stddev_internal(Int128AggState *state,
    6149              :                              bool variance, bool sample,
    6150              :                              bool *is_null)
    6151              : {
    6152              :     NumericAggState numstate;
    6153              :     Numeric     res;
    6154              : 
    6155              :     /* Initialize an empty agg state */
    6156          211 :     memset(&numstate, 0, sizeof(NumericAggState));
    6157              : 
    6158          211 :     if (state)
    6159              :     {
    6160              :         NumericVar  tmp_var;
    6161              : 
    6162          211 :         numstate.N = state->N;
    6163              : 
    6164          211 :         init_var(&tmp_var);
    6165              : 
    6166          211 :         int128_to_numericvar(state->sumX, &tmp_var);
    6167          211 :         accum_sum_add(&numstate.sumX, &tmp_var);
    6168              : 
    6169          211 :         int128_to_numericvar(state->sumX2, &tmp_var);
    6170          211 :         accum_sum_add(&numstate.sumX2, &tmp_var);
    6171              : 
    6172          211 :         free_var(&tmp_var);
    6173              :     }
    6174              : 
    6175          211 :     res = numeric_stddev_internal(&numstate, variance, sample, is_null);
    6176              : 
    6177          211 :     if (numstate.sumX.ndigits > 0)
    6178              :     {
    6179          211 :         pfree(numstate.sumX.pos_digits);
    6180          211 :         pfree(numstate.sumX.neg_digits);
    6181              :     }
    6182          211 :     if (numstate.sumX2.ndigits > 0)
    6183              :     {
    6184          211 :         pfree(numstate.sumX2.pos_digits);
    6185          211 :         pfree(numstate.sumX2.neg_digits);
    6186              :     }
    6187              : 
    6188          211 :     return res;
    6189              : }
    6190              : 
    6191              : Datum
    6192           63 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
    6193              : {
    6194              :     Int128AggState *state;
    6195              :     Numeric     res;
    6196              :     bool        is_null;
    6197              : 
    6198           63 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    6199              : 
    6200           63 :     res = numeric_poly_stddev_internal(state, true, true, &is_null);
    6201              : 
    6202           63 :     if (is_null)
    6203           12 :         PG_RETURN_NULL();
    6204              :     else
    6205           51 :         PG_RETURN_NUMERIC(res);
    6206              : }
    6207              : 
    6208              : Datum
    6209           82 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
    6210              : {
    6211              :     Int128AggState *state;
    6212              :     Numeric     res;
    6213              :     bool        is_null;
    6214              : 
    6215           82 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    6216              : 
    6217           82 :     res = numeric_poly_stddev_internal(state, false, true, &is_null);
    6218              : 
    6219           82 :     if (is_null)
    6220           12 :         PG_RETURN_NULL();
    6221              :     else
    6222           70 :         PG_RETURN_NUMERIC(res);
    6223              : }
    6224              : 
    6225              : Datum
    6226           30 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
    6227              : {
    6228              :     Int128AggState *state;
    6229              :     Numeric     res;
    6230              :     bool        is_null;
    6231              : 
    6232           30 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    6233              : 
    6234           30 :     res = numeric_poly_stddev_internal(state, true, false, &is_null);
    6235              : 
    6236           30 :     if (is_null)
    6237            0 :         PG_RETURN_NULL();
    6238              :     else
    6239           30 :         PG_RETURN_NUMERIC(res);
    6240              : }
    6241              : 
    6242              : Datum
    6243           36 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
    6244              : {
    6245              :     Int128AggState *state;
    6246              :     Numeric     res;
    6247              :     bool        is_null;
    6248              : 
    6249           36 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
    6250              : 
    6251           36 :     res = numeric_poly_stddev_internal(state, false, false, &is_null);
    6252              : 
    6253           36 :     if (is_null)
    6254            0 :         PG_RETURN_NULL();
    6255              :     else
    6256           36 :         PG_RETURN_NUMERIC(res);
    6257              : }
    6258              : 
    6259              : /*
    6260              :  * SUM transition functions for integer datatypes.
    6261              :  *
    6262              :  * To avoid overflow, we use accumulators wider than the input datatype.
    6263              :  * A Numeric accumulator is needed for int8 input; for int4 and int2
    6264              :  * inputs, we use int8 accumulators which should be sufficient for practical
    6265              :  * purposes.  (The latter two therefore don't really belong in this file,
    6266              :  * but we keep them here anyway.)
    6267              :  *
    6268              :  * Because SQL defines the SUM() of no values to be NULL, not zero,
    6269              :  * the initial condition of the transition data value needs to be NULL. This
    6270              :  * means we can't rely on ExecAgg to automatically insert the first non-null
    6271              :  * data value into the transition data: it doesn't know how to do the type
    6272              :  * conversion.  The upshot is that these routines have to be marked non-strict
    6273              :  * and handle substitution of the first non-null input themselves.
    6274              :  *
    6275              :  * Note: these functions are used only in plain aggregation mode.
    6276              :  * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
    6277              :  */
    6278              : 
    6279              : Datum
    6280           12 : int2_sum(PG_FUNCTION_ARGS)
    6281              : {
    6282              :     int64       oldsum;
    6283              :     int64       newval;
    6284              : 
    6285           12 :     if (PG_ARGISNULL(0))
    6286              :     {
    6287              :         /* No non-null input seen so far... */
    6288            3 :         if (PG_ARGISNULL(1))
    6289            0 :             PG_RETURN_NULL();   /* still no non-null */
    6290              :         /* This is the first non-null input. */
    6291            3 :         newval = (int64) PG_GETARG_INT16(1);
    6292            3 :         PG_RETURN_INT64(newval);
    6293              :     }
    6294              : 
    6295            9 :     oldsum = PG_GETARG_INT64(0);
    6296              : 
    6297              :     /* Leave sum unchanged if new input is null. */
    6298            9 :     if (PG_ARGISNULL(1))
    6299            0 :         PG_RETURN_INT64(oldsum);
    6300              : 
    6301              :     /* OK to do the addition. */
    6302            9 :     newval = oldsum + (int64) PG_GETARG_INT16(1);
    6303              : 
    6304            9 :     PG_RETURN_INT64(newval);
    6305              : }
    6306              : 
    6307              : Datum
    6308      2470450 : int4_sum(PG_FUNCTION_ARGS)
    6309              : {
    6310              :     int64       oldsum;
    6311              :     int64       newval;
    6312              : 
    6313      2470450 :     if (PG_ARGISNULL(0))
    6314              :     {
    6315              :         /* No non-null input seen so far... */
    6316       104297 :         if (PG_ARGISNULL(1))
    6317          499 :             PG_RETURN_NULL();   /* still no non-null */
    6318              :         /* This is the first non-null input. */
    6319       103798 :         newval = (int64) PG_GETARG_INT32(1);
    6320       103798 :         PG_RETURN_INT64(newval);
    6321              :     }
    6322              : 
    6323      2366153 :     oldsum = PG_GETARG_INT64(0);
    6324              : 
    6325              :     /* Leave sum unchanged if new input is null. */
    6326      2366153 :     if (PG_ARGISNULL(1))
    6327        15455 :         PG_RETURN_INT64(oldsum);
    6328              : 
    6329              :     /* OK to do the addition. */
    6330      2350698 :     newval = oldsum + (int64) PG_GETARG_INT32(1);
    6331              : 
    6332      2350698 :     PG_RETURN_INT64(newval);
    6333              : }
    6334              : 
    6335              : /*
    6336              :  * Note: this function is obsolete, it's no longer used for SUM(int8).
    6337              :  */
    6338              : Datum
    6339            0 : int8_sum(PG_FUNCTION_ARGS)
    6340              : {
    6341              :     Numeric     oldsum;
    6342              : 
    6343            0 :     if (PG_ARGISNULL(0))
    6344              :     {
    6345              :         /* No non-null input seen so far... */
    6346            0 :         if (PG_ARGISNULL(1))
    6347            0 :             PG_RETURN_NULL();   /* still no non-null */
    6348              :         /* This is the first non-null input. */
    6349            0 :         PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
    6350              :     }
    6351              : 
    6352              :     /*
    6353              :      * Note that we cannot special-case the aggregate case here, as we do for
    6354              :      * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
    6355              :      * our first parameter in-place.
    6356              :      */
    6357              : 
    6358            0 :     oldsum = PG_GETARG_NUMERIC(0);
    6359              : 
    6360              :     /* Leave sum unchanged if new input is null. */
    6361            0 :     if (PG_ARGISNULL(1))
    6362            0 :         PG_RETURN_NUMERIC(oldsum);
    6363              : 
    6364              :     /* OK to do the addition. */
    6365            0 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
    6366              :                                         NumericGetDatum(oldsum),
    6367              :                                         NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
    6368              : }
    6369              : 
    6370              : 
    6371              : /*
    6372              :  * Routines for avg(int2) and avg(int4).  The transition datatype
    6373              :  * is a two-element int8 array, holding count and sum.
    6374              :  *
    6375              :  * These functions are also used for sum(int2) and sum(int4) when
    6376              :  * operating in moving-aggregate mode, since for correct inverse transitions
    6377              :  * we need to count the inputs.
    6378              :  */
    6379              : 
    6380              : typedef struct Int8TransTypeData
    6381              : {
    6382              :     int64       count;
    6383              :     int64       sum;
    6384              : } Int8TransTypeData;
    6385              : 
    6386              : Datum
    6387           21 : int2_avg_accum(PG_FUNCTION_ARGS)
    6388              : {
    6389              :     ArrayType  *transarray;
    6390           21 :     int16       newval = PG_GETARG_INT16(1);
    6391              :     Int8TransTypeData *transdata;
    6392              : 
    6393              :     /*
    6394              :      * If we're invoked as an aggregate, we can cheat and modify our first
    6395              :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    6396              :      * a copy of it before scribbling on it.
    6397              :      */
    6398           21 :     if (AggCheckCallContext(fcinfo, NULL))
    6399           21 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    6400              :     else
    6401            0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    6402              : 
    6403           42 :     if (ARR_HASNULL(transarray) ||
    6404           21 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6405            0 :         elog(ERROR, "expected 2-element int8 array");
    6406              : 
    6407           21 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    6408           21 :     transdata->count++;
    6409           21 :     transdata->sum += newval;
    6410              : 
    6411           21 :     PG_RETURN_ARRAYTYPE_P(transarray);
    6412              : }
    6413              : 
    6414              : Datum
    6415      1313151 : int4_avg_accum(PG_FUNCTION_ARGS)
    6416              : {
    6417              :     ArrayType  *transarray;
    6418      1313151 :     int32       newval = PG_GETARG_INT32(1);
    6419              :     Int8TransTypeData *transdata;
    6420              : 
    6421              :     /*
    6422              :      * If we're invoked as an aggregate, we can cheat and modify our first
    6423              :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    6424              :      * a copy of it before scribbling on it.
    6425              :      */
    6426      1313151 :     if (AggCheckCallContext(fcinfo, NULL))
    6427      1313151 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    6428              :     else
    6429            0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    6430              : 
    6431      2626302 :     if (ARR_HASNULL(transarray) ||
    6432      1313151 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6433            0 :         elog(ERROR, "expected 2-element int8 array");
    6434              : 
    6435      1313151 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    6436      1313151 :     transdata->count++;
    6437      1313151 :     transdata->sum += newval;
    6438              : 
    6439      1313151 :     PG_RETURN_ARRAYTYPE_P(transarray);
    6440              : }
    6441              : 
    6442              : Datum
    6443         4913 : int4_avg_combine(PG_FUNCTION_ARGS)
    6444              : {
    6445              :     ArrayType  *transarray1;
    6446              :     ArrayType  *transarray2;
    6447              :     Int8TransTypeData *state1;
    6448              :     Int8TransTypeData *state2;
    6449              : 
    6450         4913 :     if (!AggCheckCallContext(fcinfo, NULL))
    6451            0 :         elog(ERROR, "aggregate function called in non-aggregate context");
    6452              : 
    6453         4913 :     transarray1 = PG_GETARG_ARRAYTYPE_P(0);
    6454         4913 :     transarray2 = PG_GETARG_ARRAYTYPE_P(1);
    6455              : 
    6456         9826 :     if (ARR_HASNULL(transarray1) ||
    6457         4913 :         ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6458            0 :         elog(ERROR, "expected 2-element int8 array");
    6459              : 
    6460         9826 :     if (ARR_HASNULL(transarray2) ||
    6461         4913 :         ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6462            0 :         elog(ERROR, "expected 2-element int8 array");
    6463              : 
    6464         4913 :     state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
    6465         4913 :     state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
    6466              : 
    6467         4913 :     state1->count += state2->count;
    6468         4913 :     state1->sum += state2->sum;
    6469              : 
    6470         4913 :     PG_RETURN_ARRAYTYPE_P(transarray1);
    6471              : }
    6472              : 
    6473              : Datum
    6474            6 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
    6475              : {
    6476              :     ArrayType  *transarray;
    6477            6 :     int16       newval = PG_GETARG_INT16(1);
    6478              :     Int8TransTypeData *transdata;
    6479              : 
    6480              :     /*
    6481              :      * If we're invoked as an aggregate, we can cheat and modify our first
    6482              :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    6483              :      * a copy of it before scribbling on it.
    6484              :      */
    6485            6 :     if (AggCheckCallContext(fcinfo, NULL))
    6486            6 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    6487              :     else
    6488            0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    6489              : 
    6490           12 :     if (ARR_HASNULL(transarray) ||
    6491            6 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6492            0 :         elog(ERROR, "expected 2-element int8 array");
    6493              : 
    6494            6 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    6495            6 :     transdata->count--;
    6496            6 :     transdata->sum -= newval;
    6497              : 
    6498            6 :     PG_RETURN_ARRAYTYPE_P(transarray);
    6499              : }
    6500              : 
    6501              : Datum
    6502          726 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
    6503              : {
    6504              :     ArrayType  *transarray;
    6505          726 :     int32       newval = PG_GETARG_INT32(1);
    6506              :     Int8TransTypeData *transdata;
    6507              : 
    6508              :     /*
    6509              :      * If we're invoked as an aggregate, we can cheat and modify our first
    6510              :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
    6511              :      * a copy of it before scribbling on it.
    6512              :      */
    6513          726 :     if (AggCheckCallContext(fcinfo, NULL))
    6514          726 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
    6515              :     else
    6516            0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    6517              : 
    6518         1452 :     if (ARR_HASNULL(transarray) ||
    6519          726 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6520            0 :         elog(ERROR, "expected 2-element int8 array");
    6521              : 
    6522          726 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    6523          726 :     transdata->count--;
    6524          726 :     transdata->sum -= newval;
    6525              : 
    6526          726 :     PG_RETURN_ARRAYTYPE_P(transarray);
    6527              : }
    6528              : 
    6529              : Datum
    6530         5417 : int8_avg(PG_FUNCTION_ARGS)
    6531              : {
    6532         5417 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    6533              :     Int8TransTypeData *transdata;
    6534              :     Datum       countd,
    6535              :                 sumd;
    6536              : 
    6537        10834 :     if (ARR_HASNULL(transarray) ||
    6538         5417 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6539            0 :         elog(ERROR, "expected 2-element int8 array");
    6540         5417 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    6541              : 
    6542              :     /* SQL defines AVG of no values to be NULL */
    6543         5417 :     if (transdata->count == 0)
    6544           59 :         PG_RETURN_NULL();
    6545              : 
    6546         5358 :     countd = NumericGetDatum(int64_to_numeric(transdata->count));
    6547         5358 :     sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
    6548              : 
    6549         5358 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
    6550              : }
    6551              : 
    6552              : /*
    6553              :  * SUM(int2) and SUM(int4) both return int8, so we can use this
    6554              :  * final function for both.
    6555              :  */
    6556              : Datum
    6557         1917 : int2int4_sum(PG_FUNCTION_ARGS)
    6558              : {
    6559         1917 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    6560              :     Int8TransTypeData *transdata;
    6561              : 
    6562         3834 :     if (ARR_HASNULL(transarray) ||
    6563         1917 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
    6564            0 :         elog(ERROR, "expected 2-element int8 array");
    6565         1917 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
    6566              : 
    6567              :     /* SQL defines SUM of no values to be NULL */
    6568         1917 :     if (transdata->count == 0)
    6569          240 :         PG_RETURN_NULL();
    6570              : 
    6571         1677 :     PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
    6572              : }
    6573              : 
    6574              : 
    6575              : /* ----------------------------------------------------------------------
    6576              :  *
    6577              :  * Debug support
    6578              :  *
    6579              :  * ----------------------------------------------------------------------
    6580              :  */
    6581              : 
    6582              : #ifdef NUMERIC_DEBUG
    6583              : 
    6584              : /*
    6585              :  * dump_numeric() - Dump a value in the db storage format for debugging
    6586              :  */
    6587              : static void
    6588              : dump_numeric(const char *str, Numeric num)
    6589              : {
    6590              :     NumericDigit *digits = NUMERIC_DIGITS(num);
    6591              :     int         ndigits;
    6592              :     int         i;
    6593              : 
    6594              :     ndigits = NUMERIC_NDIGITS(num);
    6595              : 
    6596              :     printf("%s: NUMERIC w=%d d=%d ", str,
    6597              :            NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
    6598              :     switch (NUMERIC_SIGN(num))
    6599              :     {
    6600              :         case NUMERIC_POS:
    6601              :             printf("POS");
    6602              :             break;
    6603              :         case NUMERIC_NEG:
    6604              :             printf("NEG");
    6605              :             break;
    6606              :         case NUMERIC_NAN:
    6607              :             printf("NaN");
    6608              :             break;
    6609              :         case NUMERIC_PINF:
    6610              :             printf("Infinity");
    6611              :             break;
    6612              :         case NUMERIC_NINF:
    6613              :             printf("-Infinity");
    6614              :             break;
    6615              :         default:
    6616              :             printf("SIGN=0x%x", NUMERIC_SIGN(num));
    6617              :             break;
    6618              :     }
    6619              : 
    6620              :     for (i = 0; i < ndigits; i++)
    6621              :         printf(" %0*d", DEC_DIGITS, digits[i]);
    6622              :     printf("\n");
    6623              : }
    6624              : 
    6625              : 
    6626              : /*
    6627              :  * dump_var() - Dump a value in the variable format for debugging
    6628              :  */
    6629              : static void
    6630              : dump_var(const char *str, NumericVar *var)
    6631              : {
    6632              :     int         i;
    6633              : 
    6634              :     printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
    6635              :     switch (var->sign)
    6636              :     {
    6637              :         case NUMERIC_POS:
    6638              :             printf("POS");
    6639              :             break;
    6640              :         case NUMERIC_NEG:
    6641              :             printf("NEG");
    6642              :             break;
    6643              :         case NUMERIC_NAN:
    6644              :             printf("NaN");
    6645              :             break;
    6646              :         case NUMERIC_PINF:
    6647              :             printf("Infinity");
    6648              :             break;
    6649              :         case NUMERIC_NINF:
    6650              :             printf("-Infinity");
    6651              :             break;
    6652              :         default:
    6653              :             printf("SIGN=0x%x", var->sign);
    6654              :             break;
    6655              :     }
    6656              : 
    6657              :     for (i = 0; i < var->ndigits; i++)
    6658              :         printf(" %0*d", DEC_DIGITS, var->digits[i]);
    6659              : 
    6660              :     printf("\n");
    6661              : }
    6662              : #endif                          /* NUMERIC_DEBUG */
    6663              : 
    6664              : 
    6665              : /* ----------------------------------------------------------------------
    6666              :  *
    6667              :  * Local functions follow
    6668              :  *
    6669              :  * In general, these do not support "special" (NaN or infinity) inputs;
    6670              :  * callers should handle those possibilities first.
    6671              :  * (There are one or two exceptions, noted in their header comments.)
    6672              :  *
    6673              :  * ----------------------------------------------------------------------
    6674              :  */
    6675              : 
    6676              : 
    6677              : /*
    6678              :  * alloc_var() -
    6679              :  *
    6680              :  *  Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
    6681              :  */
    6682              : static void
    6683      1091290 : alloc_var(NumericVar *var, int ndigits)
    6684              : {
    6685      1091290 :     digitbuf_free(var->buf);
    6686      1091290 :     var->buf = digitbuf_alloc(ndigits + 1);
    6687      1091290 :     var->buf[0] = 0;         /* spare digit for rounding */
    6688      1091290 :     var->digits = var->buf + 1;
    6689      1091290 :     var->ndigits = ndigits;
    6690      1091290 : }
    6691              : 
    6692              : 
    6693              : /*
    6694              :  * free_var() -
    6695              :  *
    6696              :  *  Return the digit buffer of a variable to the free pool
    6697              :  */
    6698              : static void
    6699      2097786 : free_var(NumericVar *var)
    6700              : {
    6701      2097786 :     digitbuf_free(var->buf);
    6702      2097786 :     var->buf = NULL;
    6703      2097786 :     var->digits = NULL;
    6704      2097786 :     var->sign = NUMERIC_NAN;
    6705      2097786 : }
    6706              : 
    6707              : 
    6708              : /*
    6709              :  * zero_var() -
    6710              :  *
    6711              :  *  Set a variable to ZERO.
    6712              :  *  Note: its dscale is not touched.
    6713              :  */
    6714              : static void
    6715        30493 : zero_var(NumericVar *var)
    6716              : {
    6717        30493 :     digitbuf_free(var->buf);
    6718        30493 :     var->buf = NULL;
    6719        30493 :     var->digits = NULL;
    6720        30493 :     var->ndigits = 0;
    6721        30493 :     var->weight = 0;         /* by convention; doesn't really matter */
    6722        30493 :     var->sign = NUMERIC_POS; /* anything but NAN... */
    6723        30493 : }
    6724              : 
    6725              : 
    6726              : /*
    6727              :  * set_var_from_str()
    6728              :  *
    6729              :  *  Parse a string and put the number into a variable
    6730              :  *
    6731              :  * This function does not handle leading or trailing spaces.  It returns
    6732              :  * the end+1 position parsed into *endptr, so that caller can check for
    6733              :  * trailing spaces/garbage if deemed necessary.
    6734              :  *
    6735              :  * cp is the place to actually start parsing; str is what to use in error
    6736              :  * reports.  (Typically cp would be the same except advanced over spaces.)
    6737              :  *
    6738              :  * Returns true on success, false on failure (if escontext points to an
    6739              :  * ErrorSaveContext; otherwise errors are thrown).
    6740              :  */
    6741              : static bool
    6742        94003 : set_var_from_str(const char *str, const char *cp,
    6743              :                  NumericVar *dest, const char **endptr,
    6744              :                  Node *escontext)
    6745              : {
    6746        94003 :     bool        have_dp = false;
    6747              :     int         i;
    6748              :     unsigned char *decdigits;
    6749        94003 :     int         sign = NUMERIC_POS;
    6750        94003 :     int         dweight = -1;
    6751              :     int         ddigits;
    6752        94003 :     int         dscale = 0;
    6753              :     int         weight;
    6754              :     int         ndigits;
    6755              :     int         offset;
    6756              :     NumericDigit *digits;
    6757              : 
    6758              :     /*
    6759              :      * We first parse the string to extract decimal digits and determine the
    6760              :      * correct decimal weight.  Then convert to NBASE representation.
    6761              :      */
    6762        94003 :     switch (*cp)
    6763              :     {
    6764            0 :         case '+':
    6765            0 :             sign = NUMERIC_POS;
    6766            0 :             cp++;
    6767            0 :             break;
    6768              : 
    6769          150 :         case '-':
    6770          150 :             sign = NUMERIC_NEG;
    6771          150 :             cp++;
    6772          150 :             break;
    6773              :     }
    6774              : 
    6775        94003 :     if (*cp == '.')
    6776              :     {
    6777          191 :         have_dp = true;
    6778          191 :         cp++;
    6779              :     }
    6780              : 
    6781        94003 :     if (!isdigit((unsigned char) *cp))
    6782            0 :         goto invalid_syntax;
    6783              : 
    6784        94003 :     decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
    6785              : 
    6786              :     /* leading padding for digit alignment later */
    6787        94003 :     memset(decdigits, 0, DEC_DIGITS);
    6788        94003 :     i = DEC_DIGITS;
    6789              : 
    6790       408985 :     while (*cp)
    6791              :     {
    6792       315736 :         if (isdigit((unsigned char) *cp))
    6793              :         {
    6794       305709 :             decdigits[i++] = *cp++ - '0';
    6795       305709 :             if (!have_dp)
    6796       260208 :                 dweight++;
    6797              :             else
    6798        45501 :                 dscale++;
    6799              :         }
    6800        10027 :         else if (*cp == '.')
    6801              :         {
    6802         9192 :             if (have_dp)
    6803            0 :                 goto invalid_syntax;
    6804         9192 :             have_dp = true;
    6805         9192 :             cp++;
    6806              :             /* decimal point must not be followed by underscore */
    6807         9192 :             if (*cp == '_')
    6808            3 :                 goto invalid_syntax;
    6809              :         }
    6810          835 :         else if (*cp == '_')
    6811              :         {
    6812              :             /* underscore must be followed by more digits */
    6813           93 :             cp++;
    6814           93 :             if (!isdigit((unsigned char) *cp))
    6815            9 :                 goto invalid_syntax;
    6816              :         }
    6817              :         else
    6818          742 :             break;
    6819              :     }
    6820              : 
    6821        93991 :     ddigits = i - DEC_DIGITS;
    6822              :     /* trailing padding for digit alignment later */
    6823        93991 :     memset(decdigits + i, 0, DEC_DIGITS - 1);
    6824              : 
    6825              :     /* Handle exponent, if any */
    6826        93991 :     if (*cp == 'e' || *cp == 'E')
    6827              :     {
    6828          718 :         int64       exponent = 0;
    6829          718 :         bool        neg = false;
    6830              : 
    6831              :         /*
    6832              :          * At this point, dweight and dscale can't be more than about
    6833              :          * INT_MAX/2 due to the MaxAllocSize limit on string length, so
    6834              :          * constraining the exponent similarly should be enough to prevent
    6835              :          * integer overflow in this function.  If the value is too large to
    6836              :          * fit in storage format, make_result() will complain about it later;
    6837              :          * for consistency use the same ereport errcode/text as make_result().
    6838              :          */
    6839              : 
    6840              :         /* exponent sign */
    6841          718 :         cp++;
    6842          718 :         if (*cp == '+')
    6843           77 :             cp++;
    6844          641 :         else if (*cp == '-')
    6845              :         {
    6846          317 :             neg = true;
    6847          317 :             cp++;
    6848              :         }
    6849              : 
    6850              :         /* exponent digits */
    6851          718 :         if (!isdigit((unsigned char) *cp))
    6852            3 :             goto invalid_syntax;
    6853              : 
    6854         2470 :         while (*cp)
    6855              :         {
    6856         1764 :             if (isdigit((unsigned char) *cp))
    6857              :             {
    6858         1743 :                 exponent = exponent * 10 + (*cp++ - '0');
    6859         1743 :                 if (exponent > PG_INT32_MAX / 2)
    6860            3 :                     goto out_of_range;
    6861              :             }
    6862           21 :             else if (*cp == '_')
    6863              :             {
    6864              :                 /* underscore must be followed by more digits */
    6865           21 :                 cp++;
    6866           21 :                 if (!isdigit((unsigned char) *cp))
    6867            6 :                     goto invalid_syntax;
    6868              :             }
    6869              :             else
    6870            0 :                 break;
    6871              :         }
    6872              : 
    6873          706 :         if (neg)
    6874          317 :             exponent = -exponent;
    6875              : 
    6876          706 :         dweight += (int) exponent;
    6877          706 :         dscale -= (int) exponent;
    6878          706 :         if (dscale < 0)
    6879          287 :             dscale = 0;
    6880              :     }
    6881              : 
    6882              :     /*
    6883              :      * Okay, convert pure-decimal representation to base NBASE.  First we need
    6884              :      * to determine the converted weight and ndigits.  offset is the number of
    6885              :      * decimal zeroes to insert before the first given digit to have a
    6886              :      * correctly aligned first NBASE digit.
    6887              :      */
    6888        93979 :     if (dweight >= 0)
    6889        93522 :         weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
    6890              :     else
    6891          457 :         weight = -((-dweight - 1) / DEC_DIGITS + 1);
    6892        93979 :     offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
    6893        93979 :     ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
    6894              : 
    6895        93979 :     alloc_var(dest, ndigits);
    6896        93979 :     dest->sign = sign;
    6897        93979 :     dest->weight = weight;
    6898        93979 :     dest->dscale = dscale;
    6899              : 
    6900        93979 :     i = DEC_DIGITS - offset;
    6901        93979 :     digits = dest->digits;
    6902              : 
    6903       226758 :     while (ndigits-- > 0)
    6904              :     {
    6905              : #if DEC_DIGITS == 4
    6906       132779 :         *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
    6907       132779 :                      decdigits[i + 2]) * 10 + decdigits[i + 3];
    6908              : #elif DEC_DIGITS == 2
    6909              :         *digits++ = decdigits[i] * 10 + decdigits[i + 1];
    6910              : #elif DEC_DIGITS == 1
    6911              :         *digits++ = decdigits[i];
    6912              : #else
    6913              : #error unsupported NBASE
    6914              : #endif
    6915       132779 :         i += DEC_DIGITS;
    6916              :     }
    6917              : 
    6918        93979 :     pfree(decdigits);
    6919              : 
    6920              :     /* Strip any leading/trailing zeroes, and normalize weight if zero */
    6921        93979 :     strip_var(dest);
    6922              : 
    6923              :     /* Return end+1 position for caller */
    6924        93979 :     *endptr = cp;
    6925              : 
    6926        93979 :     return true;
    6927              : 
    6928            3 : out_of_range:
    6929            3 :     ereturn(escontext, false,
    6930              :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    6931              :              errmsg("value overflows numeric format")));
    6932              : 
    6933           21 : invalid_syntax:
    6934           21 :     ereturn(escontext, false,
    6935              :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    6936              :              errmsg("invalid input syntax for type %s: \"%s\"",
    6937              :                     "numeric", str)));
    6938              : }
    6939              : 
    6940              : 
    6941              : /*
    6942              :  * Return the numeric value of a single hex digit.
    6943              :  */
    6944              : static inline int
    6945          354 : xdigit_value(char dig)
    6946              : {
    6947          447 :     return dig >= '0' && dig <= '9' ? dig - '0' :
    6948          147 :         dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
    6949           54 :         dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
    6950              : }
    6951              : 
    6952              : /*
    6953              :  * set_var_from_non_decimal_integer_str()
    6954              :  *
    6955              :  *  Parse a string containing a non-decimal integer
    6956              :  *
    6957              :  * This function does not handle leading or trailing spaces.  It returns
    6958              :  * the end+1 position parsed into *endptr, so that caller can check for
    6959              :  * trailing spaces/garbage if deemed necessary.
    6960              :  *
    6961              :  * cp is the place to actually start parsing; str is what to use in error
    6962              :  * reports.  The number's sign and base prefix indicator (e.g., "0x") are
    6963              :  * assumed to have already been parsed, so cp should point to the number's
    6964              :  * first digit in the base specified.
    6965              :  *
    6966              :  * base is expected to be 2, 8 or 16.
    6967              :  *
    6968              :  * Returns true on success, false on failure (if escontext points to an
    6969              :  * ErrorSaveContext; otherwise errors are thrown).
    6970              :  */
    6971              : static bool
    6972           78 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
    6973              :                                      int base, NumericVar *dest,
    6974              :                                      const char **endptr, Node *escontext)
    6975              : {
    6976           78 :     const char *firstdigit = cp;
    6977              :     int64       tmp;
    6978              :     int64       mul;
    6979              :     NumericVar  tmp_var;
    6980              : 
    6981           78 :     init_var(&tmp_var);
    6982              : 
    6983           78 :     zero_var(dest);
    6984              : 
    6985              :     /*
    6986              :      * Process input digits in groups that fit in int64.  Here "tmp" is the
    6987              :      * value of the digits in the group, and "mul" is base^n, where n is the
    6988              :      * number of digits in the group.  Thus tmp < mul, and we must start a new
    6989              :      * group when mul * base threatens to overflow PG_INT64_MAX.
    6990              :      */
    6991           78 :     tmp = 0;
    6992           78 :     mul = 1;
    6993              : 
    6994           78 :     if (base == 16)
    6995              :     {
    6996          414 :         while (*cp)
    6997              :         {
    6998          399 :             if (isxdigit((unsigned char) *cp))
    6999              :             {
    7000          354 :                 if (mul > PG_INT64_MAX / 16)
    7001              :                 {
    7002              :                     /* Add the contribution from this group of digits */
    7003           15 :                     int64_to_numericvar(mul, &tmp_var);
    7004           15 :                     mul_var(dest, &tmp_var, dest, 0);
    7005           15 :                     int64_to_numericvar(tmp, &tmp_var);
    7006           15 :                     add_var(dest, &tmp_var, dest);
    7007              : 
    7008              :                     /* Result will overflow if weight overflows int16 */
    7009           15 :                     if (dest->weight > NUMERIC_WEIGHT_MAX)
    7010            0 :                         goto out_of_range;
    7011              : 
    7012              :                     /* Begin a new group */
    7013           15 :                     tmp = 0;
    7014           15 :                     mul = 1;
    7015              :                 }
    7016              : 
    7017          354 :                 tmp = tmp * 16 + xdigit_value(*cp++);
    7018          354 :                 mul = mul * 16;
    7019              :             }
    7020           45 :             else if (*cp == '_')
    7021              :             {
    7022              :                 /* Underscore must be followed by more digits */
    7023           33 :                 cp++;
    7024           33 :                 if (!isxdigit((unsigned char) *cp))
    7025            9 :                     goto invalid_syntax;
    7026              :             }
    7027              :             else
    7028           12 :                 break;
    7029              :         }
    7030              :     }
    7031           42 :     else if (base == 8)
    7032              :     {
    7033          318 :         while (*cp)
    7034              :         {
    7035          303 :             if (*cp >= '0' && *cp <= '7')
    7036              :             {
    7037          279 :                 if (mul > PG_INT64_MAX / 8)
    7038              :                 {
    7039              :                     /* Add the contribution from this group of digits */
    7040            9 :                     int64_to_numericvar(mul, &tmp_var);
    7041            9 :                     mul_var(dest, &tmp_var, dest, 0);
    7042            9 :                     int64_to_numericvar(tmp, &tmp_var);
    7043            9 :                     add_var(dest, &tmp_var, dest);
    7044              : 
    7045              :                     /* Result will overflow if weight overflows int16 */
    7046            9 :                     if (dest->weight > NUMERIC_WEIGHT_MAX)
    7047            0 :                         goto out_of_range;
    7048              : 
    7049              :                     /* Begin a new group */
    7050            9 :                     tmp = 0;
    7051            9 :                     mul = 1;
    7052              :                 }
    7053              : 
    7054          279 :                 tmp = tmp * 8 + (*cp++ - '0');
    7055          279 :                 mul = mul * 8;
    7056              :             }
    7057           24 :             else if (*cp == '_')
    7058              :             {
    7059              :                 /* Underscore must be followed by more digits */
    7060           18 :                 cp++;
    7061           18 :                 if (*cp < '0' || *cp > '7')
    7062            0 :                     goto invalid_syntax;
    7063              :             }
    7064              :             else
    7065            6 :                 break;
    7066              :         }
    7067              :     }
    7068           21 :     else if (base == 2)
    7069              :     {
    7070          780 :         while (*cp)
    7071              :         {
    7072          765 :             if (*cp >= '0' && *cp <= '1')
    7073              :             {
    7074          708 :                 if (mul > PG_INT64_MAX / 2)
    7075              :                 {
    7076              :                     /* Add the contribution from this group of digits */
    7077            9 :                     int64_to_numericvar(mul, &tmp_var);
    7078            9 :                     mul_var(dest, &tmp_var, dest, 0);
    7079            9 :                     int64_to_numericvar(tmp, &tmp_var);
    7080            9 :                     add_var(dest, &tmp_var, dest);
    7081              : 
    7082              :                     /* Result will overflow if weight overflows int16 */
    7083            9 :                     if (dest->weight > NUMERIC_WEIGHT_MAX)
    7084            0 :                         goto out_of_range;
    7085              : 
    7086              :                     /* Begin a new group */
    7087            9 :                     tmp = 0;
    7088            9 :                     mul = 1;
    7089              :                 }
    7090              : 
    7091          708 :                 tmp = tmp * 2 + (*cp++ - '0');
    7092          708 :                 mul = mul * 2;
    7093              :             }
    7094           57 :             else if (*cp == '_')
    7095              :             {
    7096              :                 /* Underscore must be followed by more digits */
    7097           51 :                 cp++;
    7098           51 :                 if (*cp < '0' || *cp > '1')
    7099            0 :                     goto invalid_syntax;
    7100              :             }
    7101              :             else
    7102            6 :                 break;
    7103              :         }
    7104              :     }
    7105              :     else
    7106              :         /* Should never happen; treat as invalid input */
    7107            0 :         goto invalid_syntax;
    7108              : 
    7109              :     /* Check that we got at least one digit */
    7110           69 :     if (unlikely(cp == firstdigit))
    7111            0 :         goto invalid_syntax;
    7112              : 
    7113              :     /* Add the contribution from the final group of digits */
    7114           69 :     int64_to_numericvar(mul, &tmp_var);
    7115           69 :     mul_var(dest, &tmp_var, dest, 0);
    7116           69 :     int64_to_numericvar(tmp, &tmp_var);
    7117           69 :     add_var(dest, &tmp_var, dest);
    7118              : 
    7119           69 :     if (dest->weight > NUMERIC_WEIGHT_MAX)
    7120            0 :         goto out_of_range;
    7121              : 
    7122           69 :     dest->sign = sign;
    7123              : 
    7124           69 :     free_var(&tmp_var);
    7125              : 
    7126              :     /* Return end+1 position for caller */
    7127           69 :     *endptr = cp;
    7128              : 
    7129           69 :     return true;
    7130              : 
    7131            0 : out_of_range:
    7132            0 :     ereturn(escontext, false,
    7133              :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    7134              :              errmsg("value overflows numeric format")));
    7135              : 
    7136            9 : invalid_syntax:
    7137            9 :     ereturn(escontext, false,
    7138              :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    7139              :              errmsg("invalid input syntax for type %s: \"%s\"",
    7140              :                     "numeric", str)));
    7141              : }
    7142              : 
    7143              : 
    7144              : /*
    7145              :  * set_var_from_num() -
    7146              :  *
    7147              :  *  Convert the packed db format into a variable
    7148              :  */
    7149              : static void
    7150         6477 : set_var_from_num(Numeric num, NumericVar *dest)
    7151              : {
    7152              :     int         ndigits;
    7153              : 
    7154         6477 :     ndigits = NUMERIC_NDIGITS(num);
    7155              : 
    7156         6477 :     alloc_var(dest, ndigits);
    7157              : 
    7158         6477 :     dest->weight = NUMERIC_WEIGHT(num);
    7159         6477 :     dest->sign = NUMERIC_SIGN(num);
    7160         6477 :     dest->dscale = NUMERIC_DSCALE(num);
    7161              : 
    7162         6477 :     memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
    7163         6477 : }
    7164              : 
    7165              : 
    7166              : /*
    7167              :  * init_var_from_num() -
    7168              :  *
    7169              :  *  Initialize a variable from packed db format. The digits array is not
    7170              :  *  copied, which saves some cycles when the resulting var is not modified.
    7171              :  *  Also, there's no need to call free_var(), as long as you don't assign any
    7172              :  *  other value to it (with set_var_* functions, or by using the var as the
    7173              :  *  destination of a function like add_var())
    7174              :  *
    7175              :  *  CAUTION: Do not modify the digits buffer of a var initialized with this
    7176              :  *  function, e.g by calling round_var() or trunc_var(), as the changes will
    7177              :  *  propagate to the original Numeric! It's OK to use it as the destination
    7178              :  *  argument of one of the calculational functions, though.
    7179              :  */
    7180              : static void
    7181      2940408 : init_var_from_num(Numeric num, NumericVar *dest)
    7182              : {
    7183      2940408 :     dest->ndigits = NUMERIC_NDIGITS(num);
    7184      2940408 :     dest->weight = NUMERIC_WEIGHT(num);
    7185      2940408 :     dest->sign = NUMERIC_SIGN(num);
    7186      2940408 :     dest->dscale = NUMERIC_DSCALE(num);
    7187      2940408 :     dest->digits = NUMERIC_DIGITS(num);
    7188      2940408 :     dest->buf = NULL;            /* digits array is not palloc'd */
    7189      2940408 : }
    7190              : 
    7191              : 
    7192              : /*
    7193              :  * set_var_from_var() -
    7194              :  *
    7195              :  *  Copy one variable into another
    7196              :  */
    7197              : static void
    7198        17655 : set_var_from_var(const NumericVar *value, NumericVar *dest)
    7199              : {
    7200              :     NumericDigit *newbuf;
    7201              : 
    7202        17655 :     newbuf = digitbuf_alloc(value->ndigits + 1);
    7203        17655 :     newbuf[0] = 0;              /* spare digit for rounding */
    7204        17655 :     if (value->ndigits > 0)       /* else value->digits might be null */
    7205        17184 :         memcpy(newbuf + 1, value->digits,
    7206        17184 :                value->ndigits * sizeof(NumericDigit));
    7207              : 
    7208        17655 :     digitbuf_free(dest->buf);
    7209              : 
    7210        17655 :     memmove(dest, value, sizeof(NumericVar));
    7211        17655 :     dest->buf = newbuf;
    7212        17655 :     dest->digits = newbuf + 1;
    7213        17655 : }
    7214              : 
    7215              : 
    7216              : /*
    7217              :  * get_str_from_var() -
    7218              :  *
    7219              :  *  Convert a var to text representation (guts of numeric_out).
    7220              :  *  The var is displayed to the number of digits indicated by its dscale.
    7221              :  *  Returns a palloc'd string.
    7222              :  */
    7223              : static char *
    7224       450331 : get_str_from_var(const NumericVar *var)
    7225              : {
    7226              :     int         dscale;
    7227              :     char       *str;
    7228              :     char       *cp;
    7229              :     char       *endcp;
    7230              :     int         i;
    7231              :     int         d;
    7232              :     NumericDigit dig;
    7233              : 
    7234              : #if DEC_DIGITS > 1
    7235              :     NumericDigit d1;
    7236              : #endif
    7237              : 
    7238       450331 :     dscale = var->dscale;
    7239              : 
    7240              :     /*
    7241              :      * Allocate space for the result.
    7242              :      *
    7243              :      * i is set to the # of decimal digits before decimal point. dscale is the
    7244              :      * # of decimal digits we will print after decimal point. We may generate
    7245              :      * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
    7246              :      * need room for sign, decimal point, null terminator.
    7247              :      */
    7248       450331 :     i = (var->weight + 1) * DEC_DIGITS;
    7249       450331 :     if (i <= 0)
    7250        69242 :         i = 1;
    7251              : 
    7252       450331 :     str = palloc(i + dscale + DEC_DIGITS + 2);
    7253       450331 :     cp = str;
    7254              : 
    7255              :     /*
    7256              :      * Output a dash for negative values
    7257              :      */
    7258       450331 :     if (var->sign == NUMERIC_NEG)
    7259         4835 :         *cp++ = '-';
    7260              : 
    7261              :     /*
    7262              :      * Output all digits before the decimal point
    7263              :      */
    7264       450331 :     if (var->weight < 0)
    7265              :     {
    7266        69242 :         d = var->weight + 1;
    7267        69242 :         *cp++ = '0';
    7268              :     }
    7269              :     else
    7270              :     {
    7271       815907 :         for (d = 0; d <= var->weight; d++)
    7272              :         {
    7273       434818 :             dig = (d < var->ndigits) ? var->digits[d] : 0;
    7274              :             /* In the first digit, suppress extra leading decimal zeroes */
    7275              : #if DEC_DIGITS == 4
    7276              :             {
    7277       434818 :                 bool        putit = (d > 0);
    7278              : 
    7279       434818 :                 d1 = dig / 1000;
    7280       434818 :                 dig -= d1 * 1000;
    7281       434818 :                 putit |= (d1 > 0);
    7282       434818 :                 if (putit)
    7283        84599 :                     *cp++ = d1 + '0';
    7284       434818 :                 d1 = dig / 100;
    7285       434818 :                 dig -= d1 * 100;
    7286       434818 :                 putit |= (d1 > 0);
    7287       434818 :                 if (putit)
    7288       290242 :                     *cp++ = d1 + '0';
    7289       434818 :                 d1 = dig / 10;
    7290       434818 :                 dig -= d1 * 10;
    7291       434818 :                 putit |= (d1 > 0);
    7292       434818 :                 if (putit)
    7293       358068 :                     *cp++ = d1 + '0';
    7294       434818 :                 *cp++ = dig + '0';
    7295              :             }
    7296              : #elif DEC_DIGITS == 2
    7297              :             d1 = dig / 10;
    7298              :             dig -= d1 * 10;
    7299              :             if (d1 > 0 || d > 0)
    7300              :                 *cp++ = d1 + '0';
    7301              :             *cp++ = dig + '0';
    7302              : #elif DEC_DIGITS == 1
    7303              :             *cp++ = dig + '0';
    7304              : #else
    7305              : #error unsupported NBASE
    7306              : #endif
    7307              :         }
    7308              :     }
    7309              : 
    7310              :     /*
    7311              :      * If requested, output a decimal point and all the digits that follow it.
    7312              :      * We initially put out a multiple of DEC_DIGITS digits, then truncate if
    7313              :      * needed.
    7314              :      */
    7315       450331 :     if (dscale > 0)
    7316              :     {
    7317       322798 :         *cp++ = '.';
    7318       322798 :         endcp = cp + dscale;
    7319       957441 :         for (i = 0; i < dscale; d++, i += DEC_DIGITS)
    7320              :         {
    7321       634643 :             dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
    7322              : #if DEC_DIGITS == 4
    7323       634643 :             d1 = dig / 1000;
    7324       634643 :             dig -= d1 * 1000;
    7325       634643 :             *cp++ = d1 + '0';
    7326       634643 :             d1 = dig / 100;
    7327       634643 :             dig -= d1 * 100;
    7328       634643 :             *cp++ = d1 + '0';
    7329       634643 :             d1 = dig / 10;
    7330       634643 :             dig -= d1 * 10;
    7331       634643 :             *cp++ = d1 + '0';
    7332       634643 :             *cp++ = dig + '0';
    7333              : #elif DEC_DIGITS == 2
    7334              :             d1 = dig / 10;
    7335              :             dig -= d1 * 10;
    7336              :             *cp++ = d1 + '0';
    7337              :             *cp++ = dig + '0';
    7338              : #elif DEC_DIGITS == 1
    7339              :             *cp++ = dig + '0';
    7340              : #else
    7341              : #error unsupported NBASE
    7342              : #endif
    7343              :         }
    7344       322798 :         cp = endcp;
    7345              :     }
    7346              : 
    7347              :     /*
    7348              :      * terminate the string and return it
    7349              :      */
    7350       450331 :     *cp = '\0';
    7351       450331 :     return str;
    7352              : }
    7353              : 
    7354              : /*
    7355              :  * get_str_from_var_sci() -
    7356              :  *
    7357              :  *  Convert a var to a normalised scientific notation text representation.
    7358              :  *  This function does the heavy lifting for numeric_out_sci().
    7359              :  *
    7360              :  *  This notation has the general form a * 10^b, where a is known as the
    7361              :  *  "significand" and b is known as the "exponent".
    7362              :  *
    7363              :  *  Because we can't do superscript in ASCII (and because we want to copy
    7364              :  *  printf's behaviour) we display the exponent using E notation, with a
    7365              :  *  minimum of two exponent digits.
    7366              :  *
    7367              :  *  For example, the value 1234 could be output as 1.2e+03.
    7368              :  *
    7369              :  *  We assume that the exponent can fit into an int32.
    7370              :  *
    7371              :  *  rscale is the number of decimal digits desired after the decimal point in
    7372              :  *  the output, negative values will be treated as meaning zero.
    7373              :  *
    7374              :  *  Returns a palloc'd string.
    7375              :  */
    7376              : static char *
    7377          114 : get_str_from_var_sci(const NumericVar *var, int rscale)
    7378              : {
    7379              :     int32       exponent;
    7380              :     NumericVar  tmp_var;
    7381              :     size_t      len;
    7382              :     char       *str;
    7383              :     char       *sig_out;
    7384              : 
    7385          114 :     if (rscale < 0)
    7386            0 :         rscale = 0;
    7387              : 
    7388              :     /*
    7389              :      * Determine the exponent of this number in normalised form.
    7390              :      *
    7391              :      * This is the exponent required to represent the number with only one
    7392              :      * significant digit before the decimal place.
    7393              :      */
    7394          114 :     if (var->ndigits > 0)
    7395              :     {
    7396          105 :         exponent = (var->weight + 1) * DEC_DIGITS;
    7397              : 
    7398              :         /*
    7399              :          * Compensate for leading decimal zeroes in the first numeric digit by
    7400              :          * decrementing the exponent.
    7401              :          */
    7402          105 :         exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
    7403              :     }
    7404              :     else
    7405              :     {
    7406              :         /*
    7407              :          * If var has no digits, then it must be zero.
    7408              :          *
    7409              :          * Zero doesn't technically have a meaningful exponent in normalised
    7410              :          * notation, but we just display the exponent as zero for consistency
    7411              :          * of output.
    7412              :          */
    7413            9 :         exponent = 0;
    7414              :     }
    7415              : 
    7416              :     /*
    7417              :      * Divide var by 10^exponent to get the significand, rounding to rscale
    7418              :      * decimal digits in the process.
    7419              :      */
    7420          114 :     init_var(&tmp_var);
    7421              : 
    7422          114 :     power_ten_int(exponent, &tmp_var);
    7423          114 :     div_var(var, &tmp_var, &tmp_var, rscale, true, true);
    7424          114 :     sig_out = get_str_from_var(&tmp_var);
    7425              : 
    7426          114 :     free_var(&tmp_var);
    7427              : 
    7428              :     /*
    7429              :      * Allocate space for the result.
    7430              :      *
    7431              :      * In addition to the significand, we need room for the exponent
    7432              :      * decoration ("e"), the sign of the exponent, up to 10 digits for the
    7433              :      * exponent itself, and of course the null terminator.
    7434              :      */
    7435          114 :     len = strlen(sig_out) + 13;
    7436          114 :     str = palloc(len);
    7437          114 :     snprintf(str, len, "%se%+03d", sig_out, exponent);
    7438              : 
    7439          114 :     pfree(sig_out);
    7440              : 
    7441          114 :     return str;
    7442              : }
    7443              : 
    7444              : 
    7445              : /*
    7446              :  * numericvar_serialize - serialize NumericVar to binary format
    7447              :  *
    7448              :  * At variable level, no checks are performed on the weight or dscale, allowing
    7449              :  * us to pass around intermediate values with higher precision than supported
    7450              :  * by the numeric type.  Note: this is incompatible with numeric_send/recv(),
    7451              :  * which use 16-bit integers for these fields.
    7452              :  */
    7453              : static void
    7454           42 : numericvar_serialize(StringInfo buf, const NumericVar *var)
    7455              : {
    7456              :     int         i;
    7457              : 
    7458           42 :     pq_sendint32(buf, var->ndigits);
    7459           42 :     pq_sendint32(buf, var->weight);
    7460           42 :     pq_sendint32(buf, var->sign);
    7461           42 :     pq_sendint32(buf, var->dscale);
    7462       318861 :     for (i = 0; i < var->ndigits; i++)
    7463       318819 :         pq_sendint16(buf, var->digits[i]);
    7464           42 : }
    7465              : 
    7466              : /*
    7467              :  * numericvar_deserialize - deserialize binary format to NumericVar
    7468              :  */
    7469              : static void
    7470           42 : numericvar_deserialize(StringInfo buf, NumericVar *var)
    7471              : {
    7472              :     int         len,
    7473              :                 i;
    7474              : 
    7475           42 :     len = pq_getmsgint(buf, sizeof(int32));
    7476              : 
    7477           42 :     alloc_var(var, len);        /* sets var->ndigits */
    7478              : 
    7479           42 :     var->weight = pq_getmsgint(buf, sizeof(int32));
    7480           42 :     var->sign = pq_getmsgint(buf, sizeof(int32));
    7481           42 :     var->dscale = pq_getmsgint(buf, sizeof(int32));
    7482       318861 :     for (i = 0; i < len; i++)
    7483       318819 :         var->digits[i] = pq_getmsgint(buf, sizeof(int16));
    7484           42 : }
    7485              : 
    7486              : 
    7487              : /*
    7488              :  * duplicate_numeric() - copy a packed-format Numeric
    7489              :  *
    7490              :  * This will handle NaN and Infinity cases.
    7491              :  */
    7492              : static Numeric
    7493        13998 : duplicate_numeric(Numeric num)
    7494              : {
    7495              :     Numeric     res;
    7496              : 
    7497        13998 :     res = (Numeric) palloc(VARSIZE(num));
    7498        13998 :     memcpy(res, num, VARSIZE(num));
    7499        13998 :     return res;
    7500              : }
    7501              : 
    7502              : /*
    7503              :  * make_result_safe() -
    7504              :  *
    7505              :  *  Create the packed db numeric format in palloc()'d memory from
    7506              :  *  a variable.  This will handle NaN and Infinity cases.
    7507              :  */
    7508              : static Numeric
    7509      1908126 : make_result_safe(const NumericVar *var, Node *escontext)
    7510              : {
    7511              :     Numeric     result;
    7512      1908126 :     NumericDigit *digits = var->digits;
    7513      1908126 :     int         weight = var->weight;
    7514      1908126 :     int         sign = var->sign;
    7515              :     int         n;
    7516              :     Size        len;
    7517              : 
    7518      1908126 :     if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
    7519              :     {
    7520              :         /*
    7521              :          * Verify valid special value.  This could be just an Assert, perhaps,
    7522              :          * but it seems worthwhile to expend a few cycles to ensure that we
    7523              :          * never write any nonzero reserved bits to disk.
    7524              :          */
    7525         1641 :         if (!(sign == NUMERIC_NAN ||
    7526              :               sign == NUMERIC_PINF ||
    7527              :               sign == NUMERIC_NINF))
    7528            0 :             elog(ERROR, "invalid numeric sign value 0x%x", sign);
    7529              : 
    7530         1641 :         result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
    7531              : 
    7532         1641 :         SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
    7533         1641 :         result->choice.n_header = sign;
    7534              :         /* the header word is all we need */
    7535              : 
    7536              :         dump_numeric("make_result()", result);
    7537         1641 :         return result;
    7538              :     }
    7539              : 
    7540      1906485 :     n = var->ndigits;
    7541              : 
    7542              :     /* truncate leading zeroes */
    7543      1906503 :     while (n > 0 && *digits == 0)
    7544              :     {
    7545           18 :         digits++;
    7546           18 :         weight--;
    7547           18 :         n--;
    7548              :     }
    7549              :     /* truncate trailing zeroes */
    7550      1949159 :     while (n > 0 && digits[n - 1] == 0)
    7551        42674 :         n--;
    7552              : 
    7553              :     /* If zero result, force to weight=0 and positive sign */
    7554      1906485 :     if (n == 0)
    7555              :     {
    7556        66526 :         weight = 0;
    7557        66526 :         sign = NUMERIC_POS;
    7558              :     }
    7559              : 
    7560              :     /* Build the result */
    7561      1906485 :     if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
    7562              :     {
    7563      1905098 :         len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
    7564      1905098 :         result = (Numeric) palloc(len);
    7565      1905098 :         SET_VARSIZE(result, len);
    7566      1905098 :         result->choice.n_short.n_header =
    7567              :             (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
    7568              :              : NUMERIC_SHORT)
    7569      1905098 :             | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
    7570      1905098 :             | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
    7571      1905098 :             | (weight & NUMERIC_SHORT_WEIGHT_MASK);
    7572              :     }
    7573              :     else
    7574              :     {
    7575         1387 :         len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
    7576         1387 :         result = (Numeric) palloc(len);
    7577         1387 :         SET_VARSIZE(result, len);
    7578         1387 :         result->choice.n_long.n_sign_dscale =
    7579         1387 :             sign | (var->dscale & NUMERIC_DSCALE_MASK);
    7580         1387 :         result->choice.n_long.n_weight = weight;
    7581              :     }
    7582              : 
    7583              :     Assert(NUMERIC_NDIGITS(result) == n);
    7584      1906485 :     if (n > 0)
    7585      1839959 :         memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
    7586              : 
    7587              :     /* Check for overflow of int16 fields */
    7588      1906485 :     if (NUMERIC_WEIGHT(result) != weight ||
    7589      1906470 :         NUMERIC_DSCALE(result) != var->dscale)
    7590           15 :         ereturn(escontext, NULL,
    7591              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    7592              :                  errmsg("value overflows numeric format")));
    7593              : 
    7594              :     dump_numeric("make_result()", result);
    7595      1906470 :     return result;
    7596              : }
    7597              : 
    7598              : 
    7599              : /*
    7600              :  * make_result() -
    7601              :  *
    7602              :  *  An interface to make_result_safe() without "escontext" argument.
    7603              :  */
    7604              : static Numeric
    7605      1135323 : make_result(const NumericVar *var)
    7606              : {
    7607      1135323 :     return make_result_safe(var, NULL);
    7608              : }
    7609              : 
    7610              : 
    7611              : /*
    7612              :  * apply_typmod() -
    7613              :  *
    7614              :  *  Do bounds checking and rounding according to the specified typmod.
    7615              :  *  Note that this is only applied to normal finite values.
    7616              :  *
    7617              :  * Returns true on success, false on failure (if escontext points to an
    7618              :  * ErrorSaveContext; otherwise errors are thrown).
    7619              :  */
    7620              : static bool
    7621        84430 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
    7622              : {
    7623              :     int         precision;
    7624              :     int         scale;
    7625              :     int         maxdigits;
    7626              :     int         ddigits;
    7627              :     int         i;
    7628              : 
    7629              :     /* Do nothing if we have an invalid typmod */
    7630        84430 :     if (!is_valid_numeric_typmod(typmod))
    7631        69852 :         return true;
    7632              : 
    7633        14578 :     precision = numeric_typmod_precision(typmod);
    7634        14578 :     scale = numeric_typmod_scale(typmod);
    7635        14578 :     maxdigits = precision - scale;
    7636              : 
    7637              :     /* Round to target scale (and set var->dscale) */
    7638        14578 :     round_var(var, scale);
    7639              : 
    7640              :     /* but don't allow var->dscale to be negative */
    7641        14578 :     if (var->dscale < 0)
    7642           63 :         var->dscale = 0;
    7643              : 
    7644              :     /*
    7645              :      * Check for overflow - note we can't do this before rounding, because
    7646              :      * rounding could raise the weight.  Also note that the var's weight could
    7647              :      * be inflated by leading zeroes, which will be stripped before storage
    7648              :      * but perhaps might not have been yet. In any case, we must recognize a
    7649              :      * true zero, whose weight doesn't mean anything.
    7650              :      */
    7651        14578 :     ddigits = (var->weight + 1) * DEC_DIGITS;
    7652        14578 :     if (ddigits > maxdigits)
    7653              :     {
    7654              :         /* Determine true weight; and check for all-zero result */
    7655         3211 :         for (i = 0; i < var->ndigits; i++)
    7656              :         {
    7657         3203 :             NumericDigit dig = var->digits[i];
    7658              : 
    7659         3203 :             if (dig)
    7660              :             {
    7661              :                 /* Adjust for any high-order decimal zero digits */
    7662              : #if DEC_DIGITS == 4
    7663         3203 :                 if (dig < 10)
    7664          153 :                     ddigits -= 3;
    7665         3050 :                 else if (dig < 100)
    7666          312 :                     ddigits -= 2;
    7667         2738 :                 else if (dig < 1000)
    7668         2729 :                     ddigits -= 1;
    7669              : #elif DEC_DIGITS == 2
    7670              :                 if (dig < 10)
    7671              :                     ddigits -= 1;
    7672              : #elif DEC_DIGITS == 1
    7673              :                 /* no adjustment */
    7674              : #else
    7675              : #error unsupported NBASE
    7676              : #endif
    7677         3203 :                 if (ddigits > maxdigits)
    7678           42 :                     ereturn(escontext, false,
    7679              :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    7680              :                              errmsg("numeric field overflow"),
    7681              :                              errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
    7682              :                                        precision, scale,
    7683              :                     /* Display 10^0 as 1 */
    7684              :                                        maxdigits ? "10^" : "",
    7685              :                                        maxdigits ? maxdigits : 1
    7686              :                                        )));
    7687         3161 :                 break;
    7688              :             }
    7689            0 :             ddigits -= DEC_DIGITS;
    7690              :         }
    7691              :     }
    7692              : 
    7693        14536 :     return true;
    7694              : }
    7695              : 
    7696              : /*
    7697              :  * apply_typmod_special() -
    7698              :  *
    7699              :  *  Do bounds checking according to the specified typmod, for an Inf or NaN.
    7700              :  *  For convenience of most callers, the value is presented in packed form.
    7701              :  *
    7702              :  * Returns true on success, false on failure (if escontext points to an
    7703              :  * ErrorSaveContext; otherwise errors are thrown).
    7704              :  */
    7705              : static bool
    7706          948 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
    7707              : {
    7708              :     int         precision;
    7709              :     int         scale;
    7710              : 
    7711              :     Assert(NUMERIC_IS_SPECIAL(num));    /* caller error if not */
    7712              : 
    7713              :     /*
    7714              :      * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
    7715              :      * but it's a longstanding behavior.  Inf is rejected if we have any
    7716              :      * typmod restriction, since an infinity shouldn't be claimed to fit in
    7717              :      * any finite number of digits.
    7718              :      */
    7719          948 :     if (NUMERIC_IS_NAN(num))
    7720          399 :         return true;
    7721              : 
    7722              :     /* Do nothing if we have a default typmod (-1) */
    7723          549 :     if (!is_valid_numeric_typmod(typmod))
    7724          540 :         return true;
    7725              : 
    7726            9 :     precision = numeric_typmod_precision(typmod);
    7727            9 :     scale = numeric_typmod_scale(typmod);
    7728              : 
    7729            9 :     ereturn(escontext, false,
    7730              :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    7731              :              errmsg("numeric field overflow"),
    7732              :              errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
    7733              :                        precision, scale)));
    7734              : }
    7735              : 
    7736              : 
    7737              : /*
    7738              :  * Convert numeric to int8, rounding if needed.
    7739              :  *
    7740              :  * If overflow, return false (no error is raised).  Return true if okay.
    7741              :  */
    7742              : static bool
    7743         5215 : numericvar_to_int64(const NumericVar *var, int64 *result)
    7744              : {
    7745              :     NumericDigit *digits;
    7746              :     int         ndigits;
    7747              :     int         weight;
    7748              :     int         i;
    7749              :     int64       val;
    7750              :     bool        neg;
    7751              :     NumericVar  rounded;
    7752              : 
    7753              :     /* Round to nearest integer */
    7754         5215 :     init_var(&rounded);
    7755         5215 :     set_var_from_var(var, &rounded);
    7756         5215 :     round_var(&rounded, 0);
    7757              : 
    7758              :     /* Check for zero input */
    7759         5215 :     strip_var(&rounded);
    7760         5215 :     ndigits = rounded.ndigits;
    7761         5215 :     if (ndigits == 0)
    7762              :     {
    7763          237 :         *result = 0;
    7764          237 :         free_var(&rounded);
    7765          237 :         return true;
    7766              :     }
    7767              : 
    7768              :     /*
    7769              :      * For input like 10000000000, we must treat stripped digits as real. So
    7770              :      * the loop assumes there are weight+1 digits before the decimal point.
    7771              :      */
    7772         4978 :     weight = rounded.weight;
    7773              :     Assert(weight >= 0 && ndigits <= weight + 1);
    7774              : 
    7775              :     /*
    7776              :      * Construct the result. To avoid issues with converting a value
    7777              :      * corresponding to INT64_MIN (which can't be represented as a positive 64
    7778              :      * bit two's complement integer), accumulate value as a negative number.
    7779              :      */
    7780         4978 :     digits = rounded.digits;
    7781         4978 :     neg = (rounded.sign == NUMERIC_NEG);
    7782         4978 :     val = -digits[0];
    7783         7100 :     for (i = 1; i <= weight; i++)
    7784              :     {
    7785         2146 :         if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
    7786              :         {
    7787           15 :             free_var(&rounded);
    7788           15 :             return false;
    7789              :         }
    7790              : 
    7791         2131 :         if (i < ndigits)
    7792              :         {
    7793         1993 :             if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
    7794              :             {
    7795            9 :                 free_var(&rounded);
    7796            9 :                 return false;
    7797              :             }
    7798              :         }
    7799              :     }
    7800              : 
    7801         4954 :     free_var(&rounded);
    7802              : 
    7803         4954 :     if (!neg)
    7804              :     {
    7805         4558 :         if (unlikely(val == PG_INT64_MIN))
    7806           12 :             return false;
    7807         4546 :         val = -val;
    7808              :     }
    7809         4942 :     *result = val;
    7810              : 
    7811         4942 :     return true;
    7812              : }
    7813              : 
    7814              : /*
    7815              :  * Convert int8 value to numeric.
    7816              :  */
    7817              : static void
    7818       951169 : int64_to_numericvar(int64 val, NumericVar *var)
    7819              : {
    7820              :     uint64      uval,
    7821              :                 newuval;
    7822              :     NumericDigit *ptr;
    7823              :     int         ndigits;
    7824              : 
    7825              :     /* int64 can require at most 19 decimal digits; add one for safety */
    7826       951169 :     alloc_var(var, 20 / DEC_DIGITS);
    7827       951169 :     if (val < 0)
    7828              :     {
    7829          914 :         var->sign = NUMERIC_NEG;
    7830          914 :         uval = pg_abs_s64(val);
    7831              :     }
    7832              :     else
    7833              :     {
    7834       950255 :         var->sign = NUMERIC_POS;
    7835       950255 :         uval = val;
    7836              :     }
    7837       951169 :     var->dscale = 0;
    7838       951169 :     if (val == 0)
    7839              :     {
    7840        15389 :         var->ndigits = 0;
    7841        15389 :         var->weight = 0;
    7842        15389 :         return;
    7843              :     }
    7844       935780 :     ptr = var->digits + var->ndigits;
    7845       935780 :     ndigits = 0;
    7846              :     do
    7847              :     {
    7848      1097744 :         ptr--;
    7849      1097744 :         ndigits++;
    7850      1097744 :         newuval = uval / NBASE;
    7851      1097744 :         *ptr = uval - newuval * NBASE;
    7852      1097744 :         uval = newuval;
    7853      1097744 :     } while (uval);
    7854       935780 :     var->digits = ptr;
    7855       935780 :     var->ndigits = ndigits;
    7856       935780 :     var->weight = ndigits - 1;
    7857              : }
    7858              : 
    7859              : /*
    7860              :  * Convert numeric to uint64, rounding if needed.
    7861              :  *
    7862              :  * If overflow, return false (no error is raised).  Return true if okay.
    7863              :  */
    7864              : static bool
    7865           59 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
    7866              : {
    7867              :     NumericDigit *digits;
    7868              :     int         ndigits;
    7869              :     int         weight;
    7870              :     int         i;
    7871              :     uint64      val;
    7872              :     NumericVar  rounded;
    7873              : 
    7874              :     /* Round to nearest integer */
    7875           59 :     init_var(&rounded);
    7876           59 :     set_var_from_var(var, &rounded);
    7877           59 :     round_var(&rounded, 0);
    7878              : 
    7879              :     /* Check for zero input */
    7880           59 :     strip_var(&rounded);
    7881           59 :     ndigits = rounded.ndigits;
    7882           59 :     if (ndigits == 0)
    7883              :     {
    7884            9 :         *result = 0;
    7885            9 :         free_var(&rounded);
    7886            9 :         return true;
    7887              :     }
    7888              : 
    7889              :     /* Check for negative input */
    7890           50 :     if (rounded.sign == NUMERIC_NEG)
    7891              :     {
    7892            6 :         free_var(&rounded);
    7893            6 :         return false;
    7894              :     }
    7895              : 
    7896              :     /*
    7897              :      * For input like 10000000000, we must treat stripped digits as real. So
    7898              :      * the loop assumes there are weight+1 digits before the decimal point.
    7899              :      */
    7900           44 :     weight = rounded.weight;
    7901              :     Assert(weight >= 0 && ndigits <= weight + 1);
    7902              : 
    7903              :     /* Construct the result */
    7904           44 :     digits = rounded.digits;
    7905           44 :     val = digits[0];
    7906          129 :     for (i = 1; i <= weight; i++)
    7907              :     {
    7908           91 :         if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
    7909              :         {
    7910            0 :             free_var(&rounded);
    7911            0 :             return false;
    7912              :         }
    7913              : 
    7914           91 :         if (i < ndigits)
    7915              :         {
    7916           91 :             if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
    7917              :             {
    7918            6 :                 free_var(&rounded);
    7919            6 :                 return false;
    7920              :             }
    7921              :         }
    7922              :     }
    7923              : 
    7924           38 :     free_var(&rounded);
    7925              : 
    7926           38 :     *result = val;
    7927              : 
    7928           38 :     return true;
    7929              : }
    7930              : 
    7931              : /*
    7932              :  * Convert 128 bit integer to numeric.
    7933              :  */
    7934              : static void
    7935         4397 : int128_to_numericvar(INT128 val, NumericVar *var)
    7936              : {
    7937              :     int         sign;
    7938              :     NumericDigit *ptr;
    7939              :     int         ndigits;
    7940              :     int32       dig;
    7941              : 
    7942              :     /* int128 can require at most 39 decimal digits; add one for safety */
    7943         4397 :     alloc_var(var, 40 / DEC_DIGITS);
    7944         4397 :     sign = int128_sign(val);
    7945         4397 :     var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS;
    7946         4397 :     var->dscale = 0;
    7947         4397 :     if (sign == 0)
    7948              :     {
    7949          102 :         var->ndigits = 0;
    7950          102 :         var->weight = 0;
    7951          102 :         return;
    7952              :     }
    7953         4295 :     ptr = var->digits + var->ndigits;
    7954         4295 :     ndigits = 0;
    7955              :     do
    7956              :     {
    7957        22623 :         ptr--;
    7958        22623 :         ndigits++;
    7959        22623 :         int128_div_mod_int32(&val, NBASE, &dig);
    7960        22623 :         *ptr = (NumericDigit) abs(dig);
    7961        22623 :     } while (!int128_is_zero(val));
    7962         4295 :     var->digits = ptr;
    7963         4295 :     var->ndigits = ndigits;
    7964         4295 :     var->weight = ndigits - 1;
    7965              : }
    7966              : 
    7967              : /*
    7968              :  * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
    7969              :  */
    7970              : static double
    7971          233 : numericvar_to_double_no_overflow(const NumericVar *var)
    7972              : {
    7973              :     char       *tmp;
    7974              :     double      val;
    7975              :     char       *endptr;
    7976              : 
    7977          233 :     tmp = get_str_from_var(var);
    7978              : 
    7979              :     /* unlike float8in, we ignore ERANGE from strtod */
    7980          233 :     val = strtod(tmp, &endptr);
    7981          233 :     if (*endptr != '\0')
    7982              :     {
    7983              :         /* shouldn't happen ... */
    7984            0 :         ereport(ERROR,
    7985              :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    7986              :                  errmsg("invalid input syntax for type %s: \"%s\"",
    7987              :                         "double precision", tmp)));
    7988              :     }
    7989              : 
    7990          233 :     pfree(tmp);
    7991              : 
    7992          233 :     return val;
    7993              : }
    7994              : 
    7995              : 
    7996              : /*
    7997              :  * cmp_var() -
    7998              :  *
    7999              :  *  Compare two values on variable level.  We assume zeroes have been
    8000              :  *  truncated to no digits.
    8001              :  */
    8002              : static int
    8003        85114 : cmp_var(const NumericVar *var1, const NumericVar *var2)
    8004              : {
    8005       170228 :     return cmp_var_common(var1->digits, var1->ndigits,
    8006        85114 :                           var1->weight, var1->sign,
    8007        85114 :                           var2->digits, var2->ndigits,
    8008        85114 :                           var2->weight, var2->sign);
    8009              : }
    8010              : 
    8011              : /*
    8012              :  * cmp_var_common() -
    8013              :  *
    8014              :  *  Main routine of cmp_var(). This function can be used by both
    8015              :  *  NumericVar and Numeric.
    8016              :  */
    8017              : static int
    8018     13895773 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
    8019              :                int var1weight, int var1sign,
    8020              :                const NumericDigit *var2digits, int var2ndigits,
    8021              :                int var2weight, int var2sign)
    8022              : {
    8023     13895773 :     if (var1ndigits == 0)
    8024              :     {
    8025       321111 :         if (var2ndigits == 0)
    8026       251464 :             return 0;
    8027        69647 :         if (var2sign == NUMERIC_NEG)
    8028         2115 :             return 1;
    8029        67532 :         return -1;
    8030              :     }
    8031     13574662 :     if (var2ndigits == 0)
    8032              :     {
    8033        50722 :         if (var1sign == NUMERIC_POS)
    8034        47227 :             return 1;
    8035         3495 :         return -1;
    8036              :     }
    8037              : 
    8038     13523940 :     if (var1sign == NUMERIC_POS)
    8039              :     {
    8040     13482573 :         if (var2sign == NUMERIC_NEG)
    8041        11590 :             return 1;
    8042     13470983 :         return cmp_abs_common(var1digits, var1ndigits, var1weight,
    8043              :                               var2digits, var2ndigits, var2weight);
    8044              :     }
    8045              : 
    8046        41367 :     if (var2sign == NUMERIC_POS)
    8047        11934 :         return -1;
    8048              : 
    8049        29433 :     return cmp_abs_common(var2digits, var2ndigits, var2weight,
    8050              :                           var1digits, var1ndigits, var1weight);
    8051              : }
    8052              : 
    8053              : 
    8054              : /*
    8055              :  * add_var() -
    8056              :  *
    8057              :  *  Full version of add functionality on variable level (handling signs).
    8058              :  *  result might point to one of the operands too without danger.
    8059              :  */
    8060              : static void
    8061       309273 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    8062              : {
    8063              :     /*
    8064              :      * Decide on the signs of the two variables what to do
    8065              :      */
    8066       309273 :     if (var1->sign == NUMERIC_POS)
    8067              :     {
    8068       308490 :         if (var2->sign == NUMERIC_POS)
    8069              :         {
    8070              :             /*
    8071              :              * Both are positive result = +(ABS(var1) + ABS(var2))
    8072              :              */
    8073       208314 :             add_abs(var1, var2, result);
    8074       208314 :             result->sign = NUMERIC_POS;
    8075              :         }
    8076              :         else
    8077              :         {
    8078              :             /*
    8079              :              * var1 is positive, var2 is negative Must compare absolute values
    8080              :              */
    8081       100176 :             switch (cmp_abs(var1, var2))
    8082              :             {
    8083           96 :                 case 0:
    8084              :                     /* ----------
    8085              :                      * ABS(var1) == ABS(var2)
    8086              :                      * result = ZERO
    8087              :                      * ----------
    8088              :                      */
    8089           96 :                     zero_var(result);
    8090           96 :                     result->dscale = Max(var1->dscale, var2->dscale);
    8091           96 :                     break;
    8092              : 
    8093        93155 :                 case 1:
    8094              :                     /* ----------
    8095              :                      * ABS(var1) > ABS(var2)
    8096              :                      * result = +(ABS(var1) - ABS(var2))
    8097              :                      * ----------
    8098              :                      */
    8099        93155 :                     sub_abs(var1, var2, result);
    8100        93155 :                     result->sign = NUMERIC_POS;
    8101        93155 :                     break;
    8102              : 
    8103         6925 :                 case -1:
    8104              :                     /* ----------
    8105              :                      * ABS(var1) < ABS(var2)
    8106              :                      * result = -(ABS(var2) - ABS(var1))
    8107              :                      * ----------
    8108              :                      */
    8109         6925 :                     sub_abs(var2, var1, result);
    8110         6925 :                     result->sign = NUMERIC_NEG;
    8111         6925 :                     break;
    8112              :             }
    8113              :         }
    8114              :     }
    8115              :     else
    8116              :     {
    8117          783 :         if (var2->sign == NUMERIC_POS)
    8118              :         {
    8119              :             /* ----------
    8120              :              * var1 is negative, var2 is positive
    8121              :              * Must compare absolute values
    8122              :              * ----------
    8123              :              */
    8124          234 :             switch (cmp_abs(var1, var2))
    8125              :             {
    8126           15 :                 case 0:
    8127              :                     /* ----------
    8128              :                      * ABS(var1) == ABS(var2)
    8129              :                      * result = ZERO
    8130              :                      * ----------
    8131              :                      */
    8132           15 :                     zero_var(result);
    8133           15 :                     result->dscale = Max(var1->dscale, var2->dscale);
    8134           15 :                     break;
    8135              : 
    8136          147 :                 case 1:
    8137              :                     /* ----------
    8138              :                      * ABS(var1) > ABS(var2)
    8139              :                      * result = -(ABS(var1) - ABS(var2))
    8140              :                      * ----------
    8141              :                      */
    8142          147 :                     sub_abs(var1, var2, result);
    8143          147 :                     result->sign = NUMERIC_NEG;
    8144          147 :                     break;
    8145              : 
    8146           72 :                 case -1:
    8147              :                     /* ----------
    8148              :                      * ABS(var1) < ABS(var2)
    8149              :                      * result = +(ABS(var2) - ABS(var1))
    8150              :                      * ----------
    8151              :                      */
    8152           72 :                     sub_abs(var2, var1, result);
    8153           72 :                     result->sign = NUMERIC_POS;
    8154           72 :                     break;
    8155              :             }
    8156              :         }
    8157              :         else
    8158              :         {
    8159              :             /* ----------
    8160              :              * Both are negative
    8161              :              * result = -(ABS(var1) + ABS(var2))
    8162              :              * ----------
    8163              :              */
    8164          549 :             add_abs(var1, var2, result);
    8165          549 :             result->sign = NUMERIC_NEG;
    8166              :         }
    8167              :     }
    8168       309273 : }
    8169              : 
    8170              : 
    8171              : /*
    8172              :  * sub_var() -
    8173              :  *
    8174              :  *  Full version of sub functionality on variable level (handling signs).
    8175              :  *  result might point to one of the operands too without danger.
    8176              :  */
    8177              : static void
    8178       266497 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    8179              : {
    8180              :     /*
    8181              :      * Decide on the signs of the two variables what to do
    8182              :      */
    8183       266497 :     if (var1->sign == NUMERIC_POS)
    8184              :     {
    8185       266042 :         if (var2->sign == NUMERIC_NEG)
    8186              :         {
    8187              :             /* ----------
    8188              :              * var1 is positive, var2 is negative
    8189              :              * result = +(ABS(var1) + ABS(var2))
    8190              :              * ----------
    8191              :              */
    8192        14263 :             add_abs(var1, var2, result);
    8193        14263 :             result->sign = NUMERIC_POS;
    8194              :         }
    8195              :         else
    8196              :         {
    8197              :             /* ----------
    8198              :              * Both are positive
    8199              :              * Must compare absolute values
    8200              :              * ----------
    8201              :              */
    8202       251779 :             switch (cmp_abs(var1, var2))
    8203              :             {
    8204        24525 :                 case 0:
    8205              :                     /* ----------
    8206              :                      * ABS(var1) == ABS(var2)
    8207              :                      * result = ZERO
    8208              :                      * ----------
    8209              :                      */
    8210        24525 :                     zero_var(result);
    8211        24525 :                     result->dscale = Max(var1->dscale, var2->dscale);
    8212        24525 :                     break;
    8213              : 
    8214       222090 :                 case 1:
    8215              :                     /* ----------
    8216              :                      * ABS(var1) > ABS(var2)
    8217              :                      * result = +(ABS(var1) - ABS(var2))
    8218              :                      * ----------
    8219              :                      */
    8220       222090 :                     sub_abs(var1, var2, result);
    8221       222090 :                     result->sign = NUMERIC_POS;
    8222       222090 :                     break;
    8223              : 
    8224         5164 :                 case -1:
    8225              :                     /* ----------
    8226              :                      * ABS(var1) < ABS(var2)
    8227              :                      * result = -(ABS(var2) - ABS(var1))
    8228              :                      * ----------
    8229              :                      */
    8230         5164 :                     sub_abs(var2, var1, result);
    8231         5164 :                     result->sign = NUMERIC_NEG;
    8232         5164 :                     break;
    8233              :             }
    8234              :         }
    8235              :     }
    8236              :     else
    8237              :     {
    8238          455 :         if (var2->sign == NUMERIC_NEG)
    8239              :         {
    8240              :             /* ----------
    8241              :              * Both are negative
    8242              :              * Must compare absolute values
    8243              :              * ----------
    8244              :              */
    8245          227 :             switch (cmp_abs(var1, var2))
    8246              :             {
    8247           83 :                 case 0:
    8248              :                     /* ----------
    8249              :                      * ABS(var1) == ABS(var2)
    8250              :                      * result = ZERO
    8251              :                      * ----------
    8252              :                      */
    8253           83 :                     zero_var(result);
    8254           83 :                     result->dscale = Max(var1->dscale, var2->dscale);
    8255           83 :                     break;
    8256              : 
    8257          120 :                 case 1:
    8258              :                     /* ----------
    8259              :                      * ABS(var1) > ABS(var2)
    8260              :                      * result = -(ABS(var1) - ABS(var2))
    8261              :                      * ----------
    8262              :                      */
    8263          120 :                     sub_abs(var1, var2, result);
    8264          120 :                     result->sign = NUMERIC_NEG;
    8265          120 :                     break;
    8266              : 
    8267           24 :                 case -1:
    8268              :                     /* ----------
    8269              :                      * ABS(var1) < ABS(var2)
    8270              :                      * result = +(ABS(var2) - ABS(var1))
    8271              :                      * ----------
    8272              :                      */
    8273           24 :                     sub_abs(var2, var1, result);
    8274           24 :                     result->sign = NUMERIC_POS;
    8275           24 :                     break;
    8276              :             }
    8277              :         }
    8278              :         else
    8279              :         {
    8280              :             /* ----------
    8281              :              * var1 is negative, var2 is positive
    8282              :              * result = -(ABS(var1) + ABS(var2))
    8283              :              * ----------
    8284              :              */
    8285          228 :             add_abs(var1, var2, result);
    8286          228 :             result->sign = NUMERIC_NEG;
    8287              :         }
    8288              :     }
    8289       266497 : }
    8290              : 
    8291              : 
    8292              : /*
    8293              :  * mul_var() -
    8294              :  *
    8295              :  *  Multiplication on variable level. Product of var1 * var2 is stored
    8296              :  *  in result.  Result is rounded to no more than rscale fractional digits.
    8297              :  */
    8298              : static void
    8299       595162 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
    8300              :         int rscale)
    8301              : {
    8302              :     int         res_ndigits;
    8303              :     int         res_ndigitpairs;
    8304              :     int         res_sign;
    8305              :     int         res_weight;
    8306              :     int         pair_offset;
    8307              :     int         maxdigits;
    8308              :     int         maxdigitpairs;
    8309              :     uint64     *dig,
    8310              :                *dig_i1_off;
    8311              :     uint64      maxdig;
    8312              :     uint64      carry;
    8313              :     uint64      newdig;
    8314              :     int         var1ndigits;
    8315              :     int         var2ndigits;
    8316              :     int         var1ndigitpairs;
    8317              :     int         var2ndigitpairs;
    8318              :     NumericDigit *var1digits;
    8319              :     NumericDigit *var2digits;
    8320              :     uint32      var1digitpair;
    8321              :     uint32     *var2digitpairs;
    8322              :     NumericDigit *res_digits;
    8323              :     int         i,
    8324              :                 i1,
    8325              :                 i2,
    8326              :                 i2limit;
    8327              : 
    8328              :     /*
    8329              :      * Arrange for var1 to be the shorter of the two numbers.  This improves
    8330              :      * performance because the inner multiplication loop is much simpler than
    8331              :      * the outer loop, so it's better to have a smaller number of iterations
    8332              :      * of the outer loop.  This also reduces the number of times that the
    8333              :      * accumulator array needs to be normalized.
    8334              :      */
    8335       595162 :     if (var1->ndigits > var2->ndigits)
    8336              :     {
    8337         7627 :         const NumericVar *tmp = var1;
    8338              : 
    8339         7627 :         var1 = var2;
    8340         7627 :         var2 = tmp;
    8341              :     }
    8342              : 
    8343              :     /* copy these values into local vars for speed in inner loop */
    8344       595162 :     var1ndigits = var1->ndigits;
    8345       595162 :     var2ndigits = var2->ndigits;
    8346       595162 :     var1digits = var1->digits;
    8347       595162 :     var2digits = var2->digits;
    8348              : 
    8349       595162 :     if (var1ndigits == 0)
    8350              :     {
    8351              :         /* one or both inputs is zero; so is result */
    8352         1447 :         zero_var(result);
    8353         1447 :         result->dscale = rscale;
    8354         1447 :         return;
    8355              :     }
    8356              : 
    8357              :     /*
    8358              :      * If var1 has 1-6 digits and the exact result was requested, delegate to
    8359              :      * mul_var_short() which uses a faster direct multiplication algorithm.
    8360              :      */
    8361       593715 :     if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
    8362              :     {
    8363       579477 :         mul_var_short(var1, var2, result);
    8364       579477 :         return;
    8365              :     }
    8366              : 
    8367              :     /* Determine result sign */
    8368        14238 :     if (var1->sign == var2->sign)
    8369        13497 :         res_sign = NUMERIC_POS;
    8370              :     else
    8371          741 :         res_sign = NUMERIC_NEG;
    8372              : 
    8373              :     /*
    8374              :      * Determine the number of result digits to compute and the (maximum
    8375              :      * possible) result weight.  If the exact result would have more than
    8376              :      * rscale fractional digits, truncate the computation with
    8377              :      * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
    8378              :      * only contribute to the right of that.  (This will give the exact
    8379              :      * rounded-to-rscale answer unless carries out of the ignored positions
    8380              :      * would have propagated through more than MUL_GUARD_DIGITS digits.)
    8381              :      *
    8382              :      * Note: an exact computation could not produce more than var1ndigits +
    8383              :      * var2ndigits digits, but we allocate at least one extra output digit in
    8384              :      * case rscale-driven rounding produces a carry out of the highest exact
    8385              :      * digit.
    8386              :      *
    8387              :      * The computation itself is done using base-NBASE^2 arithmetic, so we
    8388              :      * actually process the input digits in pairs, producing a base-NBASE^2
    8389              :      * intermediate result.  This significantly improves performance, since
    8390              :      * schoolbook multiplication is O(N^2) in the number of input digits, and
    8391              :      * working in base NBASE^2 effectively halves "N".
    8392              :      *
    8393              :      * Note: in a truncated computation, we must compute at least one extra
    8394              :      * output digit to ensure that all the guard digits are fully computed.
    8395              :      */
    8396              :     /* digit pairs in each input */
    8397        14238 :     var1ndigitpairs = (var1ndigits + 1) / 2;
    8398        14238 :     var2ndigitpairs = (var2ndigits + 1) / 2;
    8399              : 
    8400              :     /* digits in exact result */
    8401        14238 :     res_ndigits = var1ndigits + var2ndigits;
    8402              : 
    8403              :     /* digit pairs in exact result with at least one extra output digit */
    8404        14238 :     res_ndigitpairs = res_ndigits / 2 + 1;
    8405              : 
    8406              :     /* pair offset to align result to end of dig[] */
    8407        14238 :     pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
    8408              : 
    8409              :     /* maximum possible result weight (odd-length inputs shifted up below) */
    8410        14238 :     res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
    8411        14238 :         res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
    8412              : 
    8413              :     /* rscale-based truncation with at least one extra output digit */
    8414        14238 :     maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
    8415              :         MUL_GUARD_DIGITS;
    8416        14238 :     maxdigitpairs = maxdigits / 2 + 1;
    8417              : 
    8418        14238 :     res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
    8419        14238 :     res_ndigits = 2 * res_ndigitpairs;
    8420              : 
    8421              :     /*
    8422              :      * In the computation below, digit pair i1 of var1 and digit pair i2 of
    8423              :      * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
    8424              :      * input digit pairs with index >= res_ndigitpairs - pair_offset don't
    8425              :      * contribute to the result, and can be ignored.
    8426              :      */
    8427        14238 :     if (res_ndigitpairs <= pair_offset)
    8428              :     {
    8429              :         /* All input digits will be ignored; so result is zero */
    8430            6 :         zero_var(result);
    8431            6 :         result->dscale = rscale;
    8432            6 :         return;
    8433              :     }
    8434        14232 :     var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
    8435        14232 :     var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
    8436              : 
    8437              :     /*
    8438              :      * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
    8439              :      * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
    8440              :      * headroom to avoid normalizing carries immediately.
    8441              :      *
    8442              :      * maxdig tracks the maximum possible value of any dig[] entry; when this
    8443              :      * threatens to exceed PG_UINT64_MAX, we take the time to propagate
    8444              :      * carries.  Furthermore, we need to ensure that overflow doesn't occur
    8445              :      * during the carry propagation passes either.  The carry values could be
    8446              :      * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
    8447              :      * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
    8448              :      *
    8449              :      * To avoid overflow in maxdig itself, it actually represents the maximum
    8450              :      * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
    8451              :      * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
    8452              :      *
    8453              :      * The conversion of var1 to base NBASE^2 is done on the fly, as each new
    8454              :      * digit is required.  The digits of var2 are converted upfront, and
    8455              :      * stored at the end of dig[].  To avoid loss of precision, the input
    8456              :      * digits are aligned with the start of digit pair array, effectively
    8457              :      * shifting them up (multiplying by NBASE) if the inputs have an odd
    8458              :      * number of NBASE digits.
    8459              :      */
    8460        14232 :     dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
    8461              :                             var2ndigitpairs * sizeof(uint32));
    8462              : 
    8463              :     /* convert var2 to base NBASE^2, shifting up if its length is odd */
    8464        14232 :     var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
    8465              : 
    8466       773595 :     for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
    8467       759363 :         var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
    8468              : 
    8469        14232 :     if (2 * i2 + 1 < var2ndigits)
    8470        10224 :         var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
    8471              :     else
    8472         4008 :         var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
    8473              : 
    8474              :     /*
    8475              :      * Start by multiplying var2 by the least significant contributing digit
    8476              :      * pair from var1, storing the results at the end of dig[], and filling
    8477              :      * the leading digits with zeros.
    8478              :      *
    8479              :      * The loop here is the same as the inner loop below, except that we set
    8480              :      * the results in dig[], rather than adding to them.  This is the
    8481              :      * performance bottleneck for multiplication, so we want to keep it simple
    8482              :      * enough so that it can be auto-vectorized.  Accordingly, process the
    8483              :      * digits left-to-right even though schoolbook multiplication would
    8484              :      * suggest right-to-left.  Since we aren't propagating carries in this
    8485              :      * loop, the order does not matter.
    8486              :      */
    8487        14232 :     i1 = var1ndigitpairs - 1;
    8488        14232 :     if (2 * i1 + 1 < var1ndigits)
    8489         6360 :         var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
    8490              :     else
    8491         7872 :         var1digitpair = var1digits[2 * i1] * NBASE;
    8492        14232 :     maxdig = var1digitpair;
    8493              : 
    8494        14232 :     i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
    8495        14232 :     dig_i1_off = &dig[i1 + pair_offset];
    8496              : 
    8497        14232 :     memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
    8498       688311 :     for (i2 = 0; i2 < i2limit; i2++)
    8499       674079 :         dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
    8500              : 
    8501              :     /*
    8502              :      * Next, multiply var2 by the remaining digit pairs from var1, adding the
    8503              :      * results to dig[] at the appropriate offsets, and normalizing whenever
    8504              :      * there is a risk of any dig[] entry overflowing.
    8505              :      */
    8506       750855 :     for (i1 = i1 - 1; i1 >= 0; i1--)
    8507              :     {
    8508       736623 :         var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
    8509       736623 :         if (var1digitpair == 0)
    8510       589758 :             continue;
    8511              : 
    8512              :         /* Time to normalize? */
    8513       146865 :         maxdig += var1digitpair;
    8514       146865 :         if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
    8515              :         {
    8516              :             /* Yes, do it (to base NBASE^2) */
    8517           15 :             carry = 0;
    8518        59982 :             for (i = res_ndigitpairs - 1; i >= 0; i--)
    8519              :             {
    8520        59967 :                 newdig = dig[i] + carry;
    8521        59967 :                 if (newdig >= NBASE_SQR)
    8522              :                 {
    8523        57621 :                     carry = newdig / NBASE_SQR;
    8524        57621 :                     newdig -= carry * NBASE_SQR;
    8525              :                 }
    8526              :                 else
    8527         2346 :                     carry = 0;
    8528        59967 :                 dig[i] = newdig;
    8529              :             }
    8530              :             Assert(carry == 0);
    8531              :             /* Reset maxdig to indicate new worst-case */
    8532           15 :             maxdig = 1 + var1digitpair;
    8533              :         }
    8534              : 
    8535              :         /* Multiply and add */
    8536       146865 :         i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
    8537       146865 :         dig_i1_off = &dig[i1 + pair_offset];
    8538              : 
    8539     62023923 :         for (i2 = 0; i2 < i2limit; i2++)
    8540     61877058 :             dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
    8541              :     }
    8542              : 
    8543              :     /*
    8544              :      * Now we do a final carry propagation pass to normalize back to base
    8545              :      * NBASE^2, and construct the base-NBASE result digits.  Note that this is
    8546              :      * still done at full precision w/guard digits.
    8547              :      */
    8548        14232 :     alloc_var(result, res_ndigits);
    8549        14232 :     res_digits = result->digits;
    8550        14232 :     carry = 0;
    8551      1441461 :     for (i = res_ndigitpairs - 1; i >= 0; i--)
    8552              :     {
    8553      1427229 :         newdig = dig[i] + carry;
    8554      1427229 :         if (newdig >= NBASE_SQR)
    8555              :         {
    8556       203457 :             carry = newdig / NBASE_SQR;
    8557       203457 :             newdig -= carry * NBASE_SQR;
    8558              :         }
    8559              :         else
    8560      1223772 :             carry = 0;
    8561      1427229 :         res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
    8562      1427229 :         res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
    8563              :     }
    8564              :     Assert(carry == 0);
    8565              : 
    8566        14232 :     pfree(dig);
    8567              : 
    8568              :     /*
    8569              :      * Finally, round the result to the requested precision.
    8570              :      */
    8571        14232 :     result->weight = res_weight;
    8572        14232 :     result->sign = res_sign;
    8573              : 
    8574              :     /* Round to target rscale (and set result->dscale) */
    8575        14232 :     round_var(result, rscale);
    8576              : 
    8577              :     /* Strip leading and trailing zeroes */
    8578        14232 :     strip_var(result);
    8579              : }
    8580              : 
    8581              : 
    8582              : /*
    8583              :  * mul_var_short() -
    8584              :  *
    8585              :  *  Special-case multiplication function used when var1 has 1-6 digits, var2
    8586              :  *  has at least as many digits as var1, and the exact product var1 * var2 is
    8587              :  *  requested.
    8588              :  */
    8589              : static void
    8590       579477 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
    8591              :               NumericVar *result)
    8592              : {
    8593       579477 :     int         var1ndigits = var1->ndigits;
    8594       579477 :     int         var2ndigits = var2->ndigits;
    8595       579477 :     NumericDigit *var1digits = var1->digits;
    8596       579477 :     NumericDigit *var2digits = var2->digits;
    8597              :     int         res_sign;
    8598              :     int         res_weight;
    8599              :     int         res_ndigits;
    8600              :     NumericDigit *res_buf;
    8601              :     NumericDigit *res_digits;
    8602       579477 :     uint32      carry = 0;
    8603              :     uint32      term;
    8604              : 
    8605              :     /* Check preconditions */
    8606              :     Assert(var1ndigits >= 1);
    8607              :     Assert(var1ndigits <= 6);
    8608              :     Assert(var2ndigits >= var1ndigits);
    8609              : 
    8610              :     /*
    8611              :      * Determine the result sign, weight, and number of digits to calculate.
    8612              :      * The weight figured here is correct if the product has no leading zero
    8613              :      * digits; otherwise strip_var() will fix things up.  Note that, unlike
    8614              :      * mul_var(), we do not need to allocate an extra output digit, because we
    8615              :      * are not rounding here.
    8616              :      */
    8617       579477 :     if (var1->sign == var2->sign)
    8618       578881 :         res_sign = NUMERIC_POS;
    8619              :     else
    8620          596 :         res_sign = NUMERIC_NEG;
    8621       579477 :     res_weight = var1->weight + var2->weight + 1;
    8622       579477 :     res_ndigits = var1ndigits + var2ndigits;
    8623              : 
    8624              :     /* Allocate result digit array */
    8625       579477 :     res_buf = digitbuf_alloc(res_ndigits + 1);
    8626       579477 :     res_buf[0] = 0;             /* spare digit for later rounding */
    8627       579477 :     res_digits = res_buf + 1;
    8628              : 
    8629              :     /*
    8630              :      * Compute the result digits in reverse, in one pass, propagating the
    8631              :      * carry up as we go.  The i'th result digit consists of the sum of the
    8632              :      * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
    8633              :      */
    8634              : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
    8635              : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
    8636              : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
    8637              : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
    8638              : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
    8639              : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
    8640              : 
    8641       579477 :     switch (var1ndigits)
    8642              :     {
    8643       576624 :         case 1:
    8644              :             /* ---------
    8645              :              * 1-digit case:
    8646              :              *      var1ndigits = 1
    8647              :              *      var2ndigits >= 1
    8648              :              *      res_ndigits = var2ndigits + 1
    8649              :              * ----------
    8650              :              */
    8651      1803170 :             for (int i = var2ndigits - 1; i >= 0; i--)
    8652              :             {
    8653      1226546 :                 term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
    8654      1226546 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
    8655      1226546 :                 carry = term / NBASE;
    8656              :             }
    8657       576624 :             res_digits[0] = (NumericDigit) carry;
    8658       576624 :             break;
    8659              : 
    8660          378 :         case 2:
    8661              :             /* ---------
    8662              :              * 2-digit case:
    8663              :              *      var1ndigits = 2
    8664              :              *      var2ndigits >= 2
    8665              :              *      res_ndigits = var2ndigits + 2
    8666              :              * ----------
    8667              :              */
    8668              :             /* last result digit and carry */
    8669          378 :             term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
    8670          378 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
    8671          378 :             carry = term / NBASE;
    8672              : 
    8673              :             /* remaining digits, except for the first two */
    8674         1152 :             for (int i = var2ndigits - 1; i >= 1; i--)
    8675              :             {
    8676          774 :                 term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
    8677          774 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
    8678          774 :                 carry = term / NBASE;
    8679              :             }
    8680          378 :             break;
    8681              : 
    8682          102 :         case 3:
    8683              :             /* ---------
    8684              :              * 3-digit case:
    8685              :              *      var1ndigits = 3
    8686              :              *      var2ndigits >= 3
    8687              :              *      res_ndigits = var2ndigits + 3
    8688              :              * ----------
    8689              :              */
    8690              :             /* last two result digits */
    8691          102 :             term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
    8692          102 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
    8693          102 :             carry = term / NBASE;
    8694              : 
    8695          102 :             term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
    8696          102 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
    8697          102 :             carry = term / NBASE;
    8698              : 
    8699              :             /* remaining digits, except for the first three */
    8700          273 :             for (int i = var2ndigits - 1; i >= 2; i--)
    8701              :             {
    8702          171 :                 term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
    8703          171 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
    8704          171 :                 carry = term / NBASE;
    8705              :             }
    8706          102 :             break;
    8707              : 
    8708         2019 :         case 4:
    8709              :             /* ---------
    8710              :              * 4-digit case:
    8711              :              *      var1ndigits = 4
    8712              :              *      var2ndigits >= 4
    8713              :              *      res_ndigits = var2ndigits + 4
    8714              :              * ----------
    8715              :              */
    8716              :             /* last three result digits */
    8717         2019 :             term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
    8718         2019 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
    8719         2019 :             carry = term / NBASE;
    8720              : 
    8721         2019 :             term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
    8722         2019 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
    8723         2019 :             carry = term / NBASE;
    8724              : 
    8725         2019 :             term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
    8726         2019 :             res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
    8727         2019 :             carry = term / NBASE;
    8728              : 
    8729              :             /* remaining digits, except for the first four */
    8730         5634 :             for (int i = var2ndigits - 1; i >= 3; i--)
    8731              :             {
    8732         3615 :                 term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
    8733         3615 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
    8734         3615 :                 carry = term / NBASE;
    8735              :             }
    8736         2019 :             break;
    8737              : 
    8738           57 :         case 5:
    8739              :             /* ---------
    8740              :              * 5-digit case:
    8741              :              *      var1ndigits = 5
    8742              :              *      var2ndigits >= 5
    8743              :              *      res_ndigits = var2ndigits + 5
    8744              :              * ----------
    8745              :              */
    8746              :             /* last four result digits */
    8747           57 :             term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
    8748           57 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
    8749           57 :             carry = term / NBASE;
    8750              : 
    8751           57 :             term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
    8752           57 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
    8753           57 :             carry = term / NBASE;
    8754              : 
    8755           57 :             term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
    8756           57 :             res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
    8757           57 :             carry = term / NBASE;
    8758              : 
    8759           57 :             term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
    8760           57 :             res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
    8761           57 :             carry = term / NBASE;
    8762              : 
    8763              :             /* remaining digits, except for the first five */
    8764          150 :             for (int i = var2ndigits - 1; i >= 4; i--)
    8765              :             {
    8766           93 :                 term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
    8767           93 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
    8768           93 :                 carry = term / NBASE;
    8769              :             }
    8770           57 :             break;
    8771              : 
    8772          297 :         case 6:
    8773              :             /* ---------
    8774              :              * 6-digit case:
    8775              :              *      var1ndigits = 6
    8776              :              *      var2ndigits >= 6
    8777              :              *      res_ndigits = var2ndigits + 6
    8778              :              * ----------
    8779              :              */
    8780              :             /* last five result digits */
    8781          297 :             term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
    8782          297 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
    8783          297 :             carry = term / NBASE;
    8784              : 
    8785          297 :             term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
    8786          297 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
    8787          297 :             carry = term / NBASE;
    8788              : 
    8789          297 :             term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
    8790          297 :             res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
    8791          297 :             carry = term / NBASE;
    8792              : 
    8793          297 :             term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
    8794          297 :             res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
    8795          297 :             carry = term / NBASE;
    8796              : 
    8797          297 :             term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
    8798          297 :             res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
    8799          297 :             carry = term / NBASE;
    8800              : 
    8801              :             /* remaining digits, except for the first six */
    8802          828 :             for (int i = var2ndigits - 1; i >= 5; i--)
    8803              :             {
    8804          531 :                 term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
    8805          531 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
    8806          531 :                 carry = term / NBASE;
    8807              :             }
    8808          297 :             break;
    8809              :     }
    8810              : 
    8811              :     /*
    8812              :      * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
    8813              :      * significant result digits.
    8814              :      */
    8815       579477 :     switch (var1ndigits)
    8816              :     {
    8817          297 :         case 6:
    8818          297 :             term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
    8819          297 :             res_digits[5] = (NumericDigit) (term % NBASE);
    8820          297 :             carry = term / NBASE;
    8821              :             pg_fallthrough;
    8822          354 :         case 5:
    8823          354 :             term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
    8824          354 :             res_digits[4] = (NumericDigit) (term % NBASE);
    8825          354 :             carry = term / NBASE;
    8826              :             pg_fallthrough;
    8827         2373 :         case 4:
    8828         2373 :             term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
    8829         2373 :             res_digits[3] = (NumericDigit) (term % NBASE);
    8830         2373 :             carry = term / NBASE;
    8831              :             pg_fallthrough;
    8832         2475 :         case 3:
    8833         2475 :             term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
    8834         2475 :             res_digits[2] = (NumericDigit) (term % NBASE);
    8835         2475 :             carry = term / NBASE;
    8836              :             pg_fallthrough;
    8837         2853 :         case 2:
    8838         2853 :             term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
    8839         2853 :             res_digits[1] = (NumericDigit) (term % NBASE);
    8840         2853 :             res_digits[0] = (NumericDigit) (term / NBASE);
    8841         2853 :             break;
    8842              :     }
    8843              : 
    8844              :     /* Store the product in result */
    8845       579477 :     digitbuf_free(result->buf);
    8846       579477 :     result->ndigits = res_ndigits;
    8847       579477 :     result->buf = res_buf;
    8848       579477 :     result->digits = res_digits;
    8849       579477 :     result->weight = res_weight;
    8850       579477 :     result->sign = res_sign;
    8851       579477 :     result->dscale = var1->dscale + var2->dscale;
    8852              : 
    8853              :     /* Strip leading and trailing zeroes */
    8854       579477 :     strip_var(result);
    8855       579477 : }
    8856              : 
    8857              : 
    8858              : /*
    8859              :  * div_var() -
    8860              :  *
    8861              :  *  Compute the quotient var1 / var2 to rscale fractional digits.
    8862              :  *
    8863              :  *  If "round" is true, the result is rounded at the rscale'th digit; if
    8864              :  *  false, it is truncated (towards zero) at that digit.
    8865              :  *
    8866              :  *  If "exact" is true, the exact result is computed to the specified rscale;
    8867              :  *  if false, successive quotient digits are approximated up to rscale plus
    8868              :  *  DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to
    8869              :  *  the right of that, before rounding or truncating to the specified rscale.
    8870              :  *  This can be significantly faster, and usually gives the same result as the
    8871              :  *  exact computation, but it may occasionally be off by one in the final
    8872              :  *  digit, if contributions from the ignored digits would have propagated
    8873              :  *  through the guard digits.  This is good enough for the transcendental
    8874              :  *  functions, where small errors are acceptable.
    8875              :  */
    8876              : static void
    8877       285621 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
    8878              :         int rscale, bool round, bool exact)
    8879              : {
    8880       285621 :     int         var1ndigits = var1->ndigits;
    8881       285621 :     int         var2ndigits = var2->ndigits;
    8882              :     int         res_sign;
    8883              :     int         res_weight;
    8884              :     int         res_ndigits;
    8885              :     int         var1ndigitpairs;
    8886              :     int         var2ndigitpairs;
    8887              :     int         res_ndigitpairs;
    8888              :     int         div_ndigitpairs;
    8889              :     int64      *dividend;
    8890              :     int32      *divisor;
    8891              :     double      fdivisor,
    8892              :                 fdivisorinverse,
    8893              :                 fdividend,
    8894              :                 fquotient;
    8895              :     int64       maxdiv;
    8896              :     int         qi;
    8897              :     int32       qdigit;
    8898              :     int64       carry;
    8899              :     int64       newdig;
    8900              :     int64      *remainder;
    8901              :     NumericDigit *res_digits;
    8902              :     int         i;
    8903              : 
    8904              :     /*
    8905              :      * First of all division by zero check; we must not be handed an
    8906              :      * unnormalized divisor.
    8907              :      */
    8908       285621 :     if (var2ndigits == 0 || var2->digits[0] == 0)
    8909            6 :         ereport(ERROR,
    8910              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    8911              :                  errmsg("division by zero")));
    8912              : 
    8913              :     /*
    8914              :      * If the divisor has just one or two digits, delegate to div_var_int(),
    8915              :      * which uses fast short division.
    8916              :      *
    8917              :      * Similarly, on platforms with 128-bit integer support, delegate to
    8918              :      * div_var_int64() for divisors with three or four digits.
    8919              :      */
    8920       285615 :     if (var2ndigits <= 2)
    8921              :     {
    8922              :         int         idivisor;
    8923              :         int         idivisor_weight;
    8924              : 
    8925       282612 :         idivisor = var2->digits[0];
    8926       282612 :         idivisor_weight = var2->weight;
    8927       282612 :         if (var2ndigits == 2)
    8928              :         {
    8929         1973 :             idivisor = idivisor * NBASE + var2->digits[1];
    8930         1973 :             idivisor_weight--;
    8931              :         }
    8932       282612 :         if (var2->sign == NUMERIC_NEG)
    8933          327 :             idivisor = -idivisor;
    8934              : 
    8935       282612 :         div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
    8936       282612 :         return;
    8937              :     }
    8938              : #ifdef HAVE_INT128
    8939         3003 :     if (var2ndigits <= 4)
    8940              :     {
    8941              :         int64       idivisor;
    8942              :         int         idivisor_weight;
    8943              : 
    8944          264 :         idivisor = var2->digits[0];
    8945          264 :         idivisor_weight = var2->weight;
    8946          984 :         for (i = 1; i < var2ndigits; i++)
    8947              :         {
    8948          720 :             idivisor = idivisor * NBASE + var2->digits[i];
    8949          720 :             idivisor_weight--;
    8950              :         }
    8951          264 :         if (var2->sign == NUMERIC_NEG)
    8952           60 :             idivisor = -idivisor;
    8953              : 
    8954          264 :         div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
    8955          264 :         return;
    8956              :     }
    8957              : #endif
    8958              : 
    8959              :     /*
    8960              :      * Otherwise, perform full long division.
    8961              :      */
    8962              : 
    8963              :     /* Result zero check */
    8964         2739 :     if (var1ndigits == 0)
    8965              :     {
    8966           18 :         zero_var(result);
    8967           18 :         result->dscale = rscale;
    8968           18 :         return;
    8969              :     }
    8970              : 
    8971              :     /*
    8972              :      * The approximate computation can be significantly faster than the exact
    8973              :      * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
    8974              :      * shorter below.  However, that comes with the tradeoff of computing
    8975              :      * DIV_GUARD_DIGITS extra base-NBASE result digits.  Ignoring all other
    8976              :      * overheads, that suggests that, in theory, the approximate computation
    8977              :      * will only be faster than the exact one when var2ndigits is greater than
    8978              :      * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
    8979              :      *
    8980              :      * Thus, we're better off doing an exact computation when var2 is shorter
    8981              :      * than this.  Empirically, it has been found that the exact threshold is
    8982              :      * a little higher, due to other overheads in the outer division loop.
    8983              :      */
    8984         2721 :     if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
    8985         1854 :         exact = true;
    8986              : 
    8987              :     /*
    8988              :      * Determine the result sign, weight and number of digits to calculate.
    8989              :      * The weight figured here is correct if the emitted quotient has no
    8990              :      * leading zero digits; otherwise strip_var() will fix things up.
    8991              :      */
    8992         2721 :     if (var1->sign == var2->sign)
    8993         2655 :         res_sign = NUMERIC_POS;
    8994              :     else
    8995           66 :         res_sign = NUMERIC_NEG;
    8996         2721 :     res_weight = var1->weight - var2->weight + 1;
    8997              :     /* The number of accurate result digits we need to produce: */
    8998         2721 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
    8999              :     /* ... but always at least 1 */
    9000         2721 :     res_ndigits = Max(res_ndigits, 1);
    9001              :     /* If rounding needed, figure one more digit to ensure correct result */
    9002         2721 :     if (round)
    9003          453 :         res_ndigits++;
    9004              :     /* Add guard digits for roundoff error when producing approx result */
    9005         2721 :     if (!exact)
    9006          861 :         res_ndigits += DIV_GUARD_DIGITS;
    9007              : 
    9008              :     /*
    9009              :      * The computation itself is done using base-NBASE^2 arithmetic, so we
    9010              :      * actually process the input digits in pairs, producing a base-NBASE^2
    9011              :      * intermediate result.  This significantly improves performance, since
    9012              :      * the computation is O(N^2) in the number of input digits, and working in
    9013              :      * base NBASE^2 effectively halves "N".
    9014              :      */
    9015         2721 :     var1ndigitpairs = (var1ndigits + 1) / 2;
    9016         2721 :     var2ndigitpairs = (var2ndigits + 1) / 2;
    9017         2721 :     res_ndigitpairs = (res_ndigits + 1) / 2;
    9018         2721 :     res_ndigits = 2 * res_ndigitpairs;
    9019              : 
    9020              :     /*
    9021              :      * We do the arithmetic in an array "dividend[]" of signed 64-bit
    9022              :      * integers.  Since PG_INT64_MAX is much larger than NBASE^4, this gives
    9023              :      * us a lot of headroom to avoid normalizing carries immediately.
    9024              :      *
    9025              :      * When performing an exact computation, the working dividend requires
    9026              :      * res_ndigitpairs + var2ndigitpairs digits.  If var1 is larger than that,
    9027              :      * the extra digits do not contribute to the result, and are ignored.
    9028              :      *
    9029              :      * When performing an approximate computation, the working dividend only
    9030              :      * requires res_ndigitpairs digits (which includes the extra guard
    9031              :      * digits).  All input digits beyond that are ignored.
    9032              :      */
    9033         2721 :     if (exact)
    9034              :     {
    9035         1860 :         div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
    9036         1860 :         var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
    9037              :     }
    9038              :     else
    9039              :     {
    9040          861 :         div_ndigitpairs = res_ndigitpairs;
    9041          861 :         var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
    9042          861 :         var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
    9043              :     }
    9044              : 
    9045              :     /*
    9046              :      * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
    9047              :      * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
    9048              :      *
    9049              :      * For convenience, we allocate one extra dividend digit, which is set to
    9050              :      * zero and not counted in div_ndigitpairs, so that the main loop below
    9051              :      * can safely read and write the (qi+1)'th digit in the approximate case.
    9052              :      */
    9053         2721 :     dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
    9054              :                                 var2ndigitpairs * sizeof(int32));
    9055         2721 :     divisor = (int32 *) (dividend + div_ndigitpairs + 1);
    9056              : 
    9057              :     /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
    9058        24729 :     for (i = 0; i < var1ndigitpairs - 1; i++)
    9059        22008 :         dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
    9060              : 
    9061         2721 :     if (2 * i + 1 < var1ndigits)
    9062         1641 :         dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
    9063              :     else
    9064         1080 :         dividend[i] = var1->digits[2 * i] * NBASE;
    9065              : 
    9066         2721 :     memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
    9067              : 
    9068              :     /* load var2 into divisor[0 .. var2ndigitpairs-1] */
    9069        19920 :     for (i = 0; i < var2ndigitpairs - 1; i++)
    9070        17199 :         divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
    9071              : 
    9072         2721 :     if (2 * i + 1 < var2ndigits)
    9073         1461 :         divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
    9074              :     else
    9075         1260 :         divisor[i] = var2->digits[2 * i] * NBASE;
    9076              : 
    9077              :     /*
    9078              :      * We estimate each quotient digit using floating-point arithmetic, taking
    9079              :      * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
    9080              :      * This must be float to avoid overflow.
    9081              :      *
    9082              :      * Since the floating-point dividend and divisor use 4 base-NBASE input
    9083              :      * digits, they include roughly 40-53 bits of information from their
    9084              :      * respective inputs (assuming NBASE is 10000), which fits well in IEEE
    9085              :      * double-precision variables.  The relative error in the floating-point
    9086              :      * quotient digit will then be less than around 2/NBASE^3, so the
    9087              :      * estimated base-NBASE^2 quotient digit will typically be correct, and
    9088              :      * should not be off by more than one from the correct value.
    9089              :      */
    9090         2721 :     fdivisor = (double) divisor[0] * NBASE_SQR;
    9091         2721 :     if (var2ndigitpairs > 1)
    9092         2721 :         fdivisor += (double) divisor[1];
    9093         2721 :     fdivisorinverse = 1.0 / fdivisor;
    9094              : 
    9095              :     /*
    9096              :      * maxdiv tracks the maximum possible absolute value of any dividend[]
    9097              :      * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
    9098              :      * propagate carries.  Furthermore, we need to ensure that overflow
    9099              :      * doesn't occur during the carry propagation passes either.  The carry
    9100              :      * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
    9101              :      * so really we must normalize when digits threaten to exceed PG_INT64_MAX
    9102              :      * - PG_INT64_MAX/NBASE^2 - 1.
    9103              :      *
    9104              :      * To avoid overflow in maxdiv itself, it represents the max absolute
    9105              :      * value divided by NBASE^2-1, i.e., at the top of the loop it is known
    9106              :      * that no dividend[] entry has an absolute value exceeding maxdiv *
    9107              :      * (NBASE^2-1).
    9108              :      *
    9109              :      * Actually, though, that holds good only for dividend[] entries after
    9110              :      * dividend[qi]; the adjustment done at the bottom of the loop may cause
    9111              :      * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
    9112              :      * the next iteration is beyond the limit.  This does not cause problems,
    9113              :      * as explained below.
    9114              :      */
    9115         2721 :     maxdiv = 1;
    9116              : 
    9117              :     /*
    9118              :      * Outer loop computes next quotient digit, which goes in dividend[qi].
    9119              :      */
    9120        24771 :     for (qi = 0; qi < res_ndigitpairs; qi++)
    9121              :     {
    9122              :         /* Approximate the current dividend value */
    9123        22050 :         fdividend = (double) dividend[qi] * NBASE_SQR;
    9124        22050 :         fdividend += (double) dividend[qi + 1];
    9125              : 
    9126              :         /* Compute the (approximate) quotient digit */
    9127        22050 :         fquotient = fdividend * fdivisorinverse;
    9128        22050 :         qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
    9129            3 :             (((int32) fquotient) - 1);  /* truncate towards -infinity */
    9130              : 
    9131        22050 :         if (qdigit != 0)
    9132              :         {
    9133              :             /* Do we need to normalize now? */
    9134        20253 :             maxdiv += i64abs(qdigit);
    9135        20253 :             if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
    9136              :             {
    9137              :                 /*
    9138              :                  * Yes, do it.  Note that if var2ndigitpairs is much smaller
    9139              :                  * than div_ndigitpairs, we can save a significant amount of
    9140              :                  * effort here by noting that we only need to normalise those
    9141              :                  * dividend[] entries touched where prior iterations
    9142              :                  * subtracted multiples of the divisor.
    9143              :                  */
    9144            3 :                 carry = 0;
    9145         3375 :                 for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
    9146              :                 {
    9147         3372 :                     newdig = dividend[i] + carry;
    9148         3372 :                     if (newdig < 0)
    9149              :                     {
    9150         3372 :                         carry = -((-newdig - 1) / NBASE_SQR) - 1;
    9151         3372 :                         newdig -= carry * NBASE_SQR;
    9152              :                     }
    9153            0 :                     else if (newdig >= NBASE_SQR)
    9154              :                     {
    9155            0 :                         carry = newdig / NBASE_SQR;
    9156            0 :                         newdig -= carry * NBASE_SQR;
    9157              :                     }
    9158              :                     else
    9159            0 :                         carry = 0;
    9160         3372 :                     dividend[i] = newdig;
    9161              :                 }
    9162            3 :                 dividend[qi] += carry;
    9163              : 
    9164              :                 /*
    9165              :                  * All the dividend[] digits except possibly dividend[qi] are
    9166              :                  * now in the range 0..NBASE^2-1.  We do not need to consider
    9167              :                  * dividend[qi] in the maxdiv value anymore, so we can reset
    9168              :                  * maxdiv to 1.
    9169              :                  */
    9170            3 :                 maxdiv = 1;
    9171              : 
    9172              :                 /*
    9173              :                  * Recompute the quotient digit since new info may have
    9174              :                  * propagated into the top two dividend digits.
    9175              :                  */
    9176            3 :                 fdividend = (double) dividend[qi] * NBASE_SQR;
    9177            3 :                 fdividend += (double) dividend[qi + 1];
    9178            3 :                 fquotient = fdividend * fdivisorinverse;
    9179            3 :                 qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
    9180            0 :                     (((int32) fquotient) - 1);  /* truncate towards -infinity */
    9181              : 
    9182            3 :                 maxdiv += i64abs(qdigit);
    9183              :             }
    9184              : 
    9185              :             /*
    9186              :              * Subtract off the appropriate multiple of the divisor.
    9187              :              *
    9188              :              * The digits beyond dividend[qi] cannot overflow, because we know
    9189              :              * they will fall within the maxdiv limit.  As for dividend[qi]
    9190              :              * itself, note that qdigit is approximately trunc(dividend[qi] /
    9191              :              * divisor[0]), which would make the new value simply dividend[qi]
    9192              :              * mod divisor[0].  The lower-order terms in qdigit can change
    9193              :              * this result by not more than about twice PG_INT64_MAX/NBASE^2,
    9194              :              * so overflow is impossible.
    9195              :              *
    9196              :              * This inner loop is the performance bottleneck for division, so
    9197              :              * code it in the same way as the inner loop of mul_var() so that
    9198              :              * it can be auto-vectorized.
    9199              :              */
    9200        20253 :             if (qdigit != 0)
    9201              :             {
    9202        20253 :                 int         istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
    9203        20253 :                 int64      *dividend_qi = &dividend[qi];
    9204              : 
    9205      3930627 :                 for (i = 0; i < istop; i++)
    9206      3910374 :                     dividend_qi[i] -= (int64) qdigit * divisor[i];
    9207              :             }
    9208              :         }
    9209              : 
    9210              :         /*
    9211              :          * The dividend digit we are about to replace might still be nonzero.
    9212              :          * Fold it into the next digit position.
    9213              :          *
    9214              :          * There is no risk of overflow here, although proving that requires
    9215              :          * some care.  Much as with the argument for dividend[qi] not
    9216              :          * overflowing, if we consider the first two terms in the numerator
    9217              :          * and denominator of qdigit, we can see that the final value of
    9218              :          * dividend[qi + 1] will be approximately a remainder mod
    9219              :          * (divisor[0]*NBASE^2 + divisor[1]).  Accounting for the lower-order
    9220              :          * terms is a bit complicated but ends up adding not much more than
    9221              :          * PG_INT64_MAX/NBASE^2 to the possible range.  Thus, dividend[qi + 1]
    9222              :          * cannot overflow here, and in its role as dividend[qi] in the next
    9223              :          * loop iteration, it can't be large enough to cause overflow in the
    9224              :          * carry propagation step (if any), either.
    9225              :          *
    9226              :          * But having said that: dividend[qi] can be more than
    9227              :          * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
    9228              :          * dividend[qi] * NBASE^2 *can* overflow.  When that happens, adding
    9229              :          * it to dividend[qi + 1] will always cause a canceling overflow so
    9230              :          * that the end result is correct.  We could avoid the intermediate
    9231              :          * overflow by doing the multiplication and addition using unsigned
    9232              :          * int64 arithmetic, which is modulo 2^64, but so far there appears no
    9233              :          * need.
    9234              :          */
    9235        22050 :         dividend[qi + 1] += dividend[qi] * NBASE_SQR;
    9236              : 
    9237        22050 :         dividend[qi] = qdigit;
    9238              :     }
    9239              : 
    9240              :     /*
    9241              :      * If an exact result was requested, use the remainder to correct the
    9242              :      * approximate quotient.  The remainder is in dividend[], immediately
    9243              :      * after the quotient digits.  Note, however, that although the remainder
    9244              :      * starts at dividend[qi = res_ndigitpairs], the first digit is the result
    9245              :      * of folding two remainder digits into one above, and the remainder
    9246              :      * currently only occupies var2ndigitpairs - 1 digits (the last digit of
    9247              :      * the working dividend was untouched by the computation above).  Thus we
    9248              :      * expand the remainder down by one base-NBASE^2 digit when we normalize
    9249              :      * it, so that it completely fills the last var2ndigitpairs digits of the
    9250              :      * dividend array.
    9251              :      */
    9252         2721 :     if (exact)
    9253              :     {
    9254              :         /* Normalize the remainder, expanding it down by one digit */
    9255         1860 :         remainder = &dividend[qi];
    9256         1860 :         carry = 0;
    9257        10107 :         for (i = var2ndigitpairs - 2; i >= 0; i--)
    9258              :         {
    9259         8247 :             newdig = remainder[i] + carry;
    9260         8247 :             if (newdig < 0)
    9261              :             {
    9262         6366 :                 carry = -((-newdig - 1) / NBASE_SQR) - 1;
    9263         6366 :                 newdig -= carry * NBASE_SQR;
    9264              :             }
    9265         1881 :             else if (newdig >= NBASE_SQR)
    9266              :             {
    9267         1842 :                 carry = newdig / NBASE_SQR;
    9268         1842 :                 newdig -= carry * NBASE_SQR;
    9269              :             }
    9270              :             else
    9271           39 :                 carry = 0;
    9272         8247 :             remainder[i + 1] = newdig;
    9273              :         }
    9274         1860 :         remainder[0] = carry;
    9275              : 
    9276         1860 :         if (remainder[0] < 0)
    9277              :         {
    9278              :             /*
    9279              :              * The remainder is negative, so the approximate quotient is too
    9280              :              * large.  Correct by reducing the quotient by one and adding the
    9281              :              * divisor to the remainder until the remainder is positive.  We
    9282              :              * expect the quotient to be off by at most one, which has been
    9283              :              * borne out in all testing, but not conclusively proven, so we
    9284              :              * allow for larger corrections, just in case.
    9285              :              */
    9286              :             do
    9287              :             {
    9288              :                 /* Add the divisor to the remainder */
    9289            3 :                 carry = 0;
    9290           39 :                 for (i = var2ndigitpairs - 1; i > 0; i--)
    9291              :                 {
    9292           36 :                     newdig = remainder[i] + divisor[i] + carry;
    9293           36 :                     if (newdig >= NBASE_SQR)
    9294              :                     {
    9295            0 :                         remainder[i] = newdig - NBASE_SQR;
    9296            0 :                         carry = 1;
    9297              :                     }
    9298              :                     else
    9299              :                     {
    9300           36 :                         remainder[i] = newdig;
    9301           36 :                         carry = 0;
    9302              :                     }
    9303              :                 }
    9304            3 :                 remainder[0] += divisor[0] + carry;
    9305              : 
    9306              :                 /* Subtract 1 from the quotient (propagating carries later) */
    9307            3 :                 dividend[qi - 1]--;
    9308              : 
    9309            3 :             } while (remainder[0] < 0);
    9310              :         }
    9311              :         else
    9312              :         {
    9313              :             /*
    9314              :              * The remainder is nonnegative.  If it's greater than or equal to
    9315              :              * the divisor, then the approximate quotient is too small and
    9316              :              * must be corrected.  As above, we don't expect to have to apply
    9317              :              * more than one correction, but allow for it just in case.
    9318              :              */
    9319              :             while (true)
    9320            3 :             {
    9321         1860 :                 bool        less = false;
    9322              : 
    9323              :                 /* Is remainder < divisor? */
    9324         1869 :                 for (i = 0; i < var2ndigitpairs; i++)
    9325              :                 {
    9326         1866 :                     if (remainder[i] < divisor[i])
    9327              :                     {
    9328         1857 :                         less = true;
    9329         1857 :                         break;
    9330              :                     }
    9331            9 :                     if (remainder[i] > divisor[i])
    9332            0 :                         break;  /* remainder > divisor */
    9333              :                 }
    9334         1860 :                 if (less)
    9335         1857 :                     break;      /* quotient is correct */
    9336              : 
    9337              :                 /* Subtract the divisor from the remainder */
    9338            3 :                 carry = 0;
    9339            9 :                 for (i = var2ndigitpairs - 1; i > 0; i--)
    9340              :                 {
    9341            6 :                     newdig = remainder[i] - divisor[i] + carry;
    9342            6 :                     if (newdig < 0)
    9343              :                     {
    9344            0 :                         remainder[i] = newdig + NBASE_SQR;
    9345            0 :                         carry = -1;
    9346              :                     }
    9347              :                     else
    9348              :                     {
    9349            6 :                         remainder[i] = newdig;
    9350            6 :                         carry = 0;
    9351              :                     }
    9352              :                 }
    9353            3 :                 remainder[0] = remainder[0] - divisor[0] + carry;
    9354              : 
    9355              :                 /* Add 1 to the quotient (propagating carries later) */
    9356            3 :                 dividend[qi - 1]++;
    9357              :             }
    9358              :         }
    9359              :     }
    9360              : 
    9361              :     /*
    9362              :      * Because the quotient digits were estimates that might have been off by
    9363              :      * one (and we didn't bother propagating carries when adjusting the
    9364              :      * quotient above), some quotient digits might be out of range, so do a
    9365              :      * final carry propagation pass to normalize back to base NBASE^2, and
    9366              :      * construct the base-NBASE result digits.  Note that this is still done
    9367              :      * at full precision w/guard digits.
    9368              :      */
    9369         2721 :     alloc_var(result, res_ndigits);
    9370         2721 :     res_digits = result->digits;
    9371         2721 :     carry = 0;
    9372        24771 :     for (i = res_ndigitpairs - 1; i >= 0; i--)
    9373              :     {
    9374        22050 :         newdig = dividend[i] + carry;
    9375        22050 :         if (newdig < 0)
    9376              :         {
    9377            3 :             carry = -((-newdig - 1) / NBASE_SQR) - 1;
    9378            3 :             newdig -= carry * NBASE_SQR;
    9379              :         }
    9380        22047 :         else if (newdig >= NBASE_SQR)
    9381              :         {
    9382            0 :             carry = newdig / NBASE_SQR;
    9383            0 :             newdig -= carry * NBASE_SQR;
    9384              :         }
    9385              :         else
    9386        22047 :             carry = 0;
    9387        22050 :         res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
    9388        22050 :         res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
    9389              :     }
    9390              :     Assert(carry == 0);
    9391              : 
    9392         2721 :     pfree(dividend);
    9393              : 
    9394              :     /*
    9395              :      * Finally, round or truncate the result to the requested precision.
    9396              :      */
    9397         2721 :     result->weight = res_weight;
    9398         2721 :     result->sign = res_sign;
    9399              : 
    9400              :     /* Round or truncate to target rscale (and set result->dscale) */
    9401         2721 :     if (round)
    9402          453 :         round_var(result, rscale);
    9403              :     else
    9404         2268 :         trunc_var(result, rscale);
    9405              : 
    9406              :     /* Strip leading and trailing zeroes */
    9407         2721 :     strip_var(result);
    9408              : }
    9409              : 
    9410              : 
    9411              : /*
    9412              :  * div_var_int() -
    9413              :  *
    9414              :  *  Divide a numeric variable by a 32-bit integer with the specified weight.
    9415              :  *  The quotient var / (ival * NBASE^ival_weight) is stored in result.
    9416              :  */
    9417              : static void
    9418       292191 : div_var_int(const NumericVar *var, int ival, int ival_weight,
    9419              :             NumericVar *result, int rscale, bool round)
    9420              : {
    9421       292191 :     NumericDigit *var_digits = var->digits;
    9422       292191 :     int         var_ndigits = var->ndigits;
    9423              :     int         res_sign;
    9424              :     int         res_weight;
    9425              :     int         res_ndigits;
    9426              :     NumericDigit *res_buf;
    9427              :     NumericDigit *res_digits;
    9428              :     uint32      divisor;
    9429              :     int         i;
    9430              : 
    9431              :     /* Guard against division by zero */
    9432       292191 :     if (ival == 0)
    9433            0 :         ereport(ERROR,
    9434              :                 errcode(ERRCODE_DIVISION_BY_ZERO),
    9435              :                 errmsg("division by zero"));
    9436              : 
    9437              :     /* Result zero check */
    9438       292191 :     if (var_ndigits == 0)
    9439              :     {
    9440         1150 :         zero_var(result);
    9441         1150 :         result->dscale = rscale;
    9442         1150 :         return;
    9443              :     }
    9444              : 
    9445              :     /*
    9446              :      * Determine the result sign, weight and number of digits to calculate.
    9447              :      * The weight figured here is correct if the emitted quotient has no
    9448              :      * leading zero digits; otherwise strip_var() will fix things up.
    9449              :      */
    9450       291041 :     if (var->sign == NUMERIC_POS)
    9451       289547 :         res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
    9452              :     else
    9453         1494 :         res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
    9454       291041 :     res_weight = var->weight - ival_weight;
    9455              :     /* The number of accurate result digits we need to produce: */
    9456       291041 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
    9457              :     /* ... but always at least 1 */
    9458       291041 :     res_ndigits = Max(res_ndigits, 1);
    9459              :     /* If rounding needed, figure one more digit to ensure correct result */
    9460       291041 :     if (round)
    9461        83373 :         res_ndigits++;
    9462              : 
    9463       291041 :     res_buf = digitbuf_alloc(res_ndigits + 1);
    9464       291041 :     res_buf[0] = 0;             /* spare digit for later rounding */
    9465       291041 :     res_digits = res_buf + 1;
    9466              : 
    9467              :     /*
    9468              :      * Now compute the quotient digits.  This is the short division algorithm
    9469              :      * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
    9470              :      * allow the divisor to exceed the internal base.
    9471              :      *
    9472              :      * In this algorithm, the carry from one digit to the next is at most
    9473              :      * divisor - 1.  Therefore, while processing the next digit, carry may
    9474              :      * become as large as divisor * NBASE - 1, and so it requires a 64-bit
    9475              :      * integer if this exceeds UINT_MAX.
    9476              :      */
    9477       291041 :     divisor = abs(ival);
    9478              : 
    9479       291041 :     if (divisor <= UINT_MAX / NBASE)
    9480              :     {
    9481              :         /* carry cannot overflow 32 bits */
    9482       289368 :         uint32      carry = 0;
    9483              : 
    9484      1422693 :         for (i = 0; i < res_ndigits; i++)
    9485              :         {
    9486      1133325 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
    9487      1133325 :             res_digits[i] = (NumericDigit) (carry / divisor);
    9488      1133325 :             carry = carry % divisor;
    9489              :         }
    9490              :     }
    9491              :     else
    9492              :     {
    9493              :         /* carry may exceed 32 bits */
    9494         1673 :         uint64      carry = 0;
    9495              : 
    9496         5352 :         for (i = 0; i < res_ndigits; i++)
    9497              :         {
    9498         3679 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
    9499         3679 :             res_digits[i] = (NumericDigit) (carry / divisor);
    9500         3679 :             carry = carry % divisor;
    9501              :         }
    9502              :     }
    9503              : 
    9504              :     /* Store the quotient in result */
    9505       291041 :     digitbuf_free(result->buf);
    9506       291041 :     result->ndigits = res_ndigits;
    9507       291041 :     result->buf = res_buf;
    9508       291041 :     result->digits = res_digits;
    9509       291041 :     result->weight = res_weight;
    9510       291041 :     result->sign = res_sign;
    9511              : 
    9512              :     /* Round or truncate to target rscale (and set result->dscale) */
    9513       291041 :     if (round)
    9514        83373 :         round_var(result, rscale);
    9515              :     else
    9516       207668 :         trunc_var(result, rscale);
    9517              : 
    9518              :     /* Strip leading/trailing zeroes */
    9519       291041 :     strip_var(result);
    9520              : }
    9521              : 
    9522              : 
    9523              : #ifdef HAVE_INT128
    9524              : /*
    9525              :  * div_var_int64() -
    9526              :  *
    9527              :  *  Divide a numeric variable by a 64-bit integer with the specified weight.
    9528              :  *  The quotient var / (ival * NBASE^ival_weight) is stored in result.
    9529              :  *
    9530              :  *  This duplicates the logic in div_var_int(), so any changes made there
    9531              :  *  should be made here too.
    9532              :  */
    9533              : static void
    9534          264 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
    9535              :               NumericVar *result, int rscale, bool round)
    9536              : {
    9537          264 :     NumericDigit *var_digits = var->digits;
    9538          264 :     int         var_ndigits = var->ndigits;
    9539              :     int         res_sign;
    9540              :     int         res_weight;
    9541              :     int         res_ndigits;
    9542              :     NumericDigit *res_buf;
    9543              :     NumericDigit *res_digits;
    9544              :     uint64      divisor;
    9545              :     int         i;
    9546              : 
    9547              :     /* Guard against division by zero */
    9548          264 :     if (ival == 0)
    9549            0 :         ereport(ERROR,
    9550              :                 errcode(ERRCODE_DIVISION_BY_ZERO),
    9551              :                 errmsg("division by zero"));
    9552              : 
    9553              :     /* Result zero check */
    9554          264 :     if (var_ndigits == 0)
    9555              :     {
    9556           48 :         zero_var(result);
    9557           48 :         result->dscale = rscale;
    9558           48 :         return;
    9559              :     }
    9560              : 
    9561              :     /*
    9562              :      * Determine the result sign, weight and number of digits to calculate.
    9563              :      * The weight figured here is correct if the emitted quotient has no
    9564              :      * leading zero digits; otherwise strip_var() will fix things up.
    9565              :      */
    9566          216 :     if (var->sign == NUMERIC_POS)
    9567          129 :         res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
    9568              :     else
    9569           87 :         res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
    9570          216 :     res_weight = var->weight - ival_weight;
    9571              :     /* The number of accurate result digits we need to produce: */
    9572          216 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
    9573              :     /* ... but always at least 1 */
    9574          216 :     res_ndigits = Max(res_ndigits, 1);
    9575              :     /* If rounding needed, figure one more digit to ensure correct result */
    9576          216 :     if (round)
    9577          213 :         res_ndigits++;
    9578              : 
    9579          216 :     res_buf = digitbuf_alloc(res_ndigits + 1);
    9580          216 :     res_buf[0] = 0;             /* spare digit for later rounding */
    9581          216 :     res_digits = res_buf + 1;
    9582              : 
    9583              :     /*
    9584              :      * Now compute the quotient digits.  This is the short division algorithm
    9585              :      * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
    9586              :      * allow the divisor to exceed the internal base.
    9587              :      *
    9588              :      * In this algorithm, the carry from one digit to the next is at most
    9589              :      * divisor - 1.  Therefore, while processing the next digit, carry may
    9590              :      * become as large as divisor * NBASE - 1, and so it requires a 128-bit
    9591              :      * integer if this exceeds PG_UINT64_MAX.
    9592              :      */
    9593          216 :     divisor = i64abs(ival);
    9594              : 
    9595          216 :     if (divisor <= PG_UINT64_MAX / NBASE)
    9596              :     {
    9597              :         /* carry cannot overflow 64 bits */
    9598          168 :         uint64      carry = 0;
    9599              : 
    9600         1707 :         for (i = 0; i < res_ndigits; i++)
    9601              :         {
    9602         1539 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
    9603         1539 :             res_digits[i] = (NumericDigit) (carry / divisor);
    9604         1539 :             carry = carry % divisor;
    9605              :         }
    9606              :     }
    9607              :     else
    9608              :     {
    9609              :         /* carry may exceed 64 bits */
    9610           48 :         uint128     carry = 0;
    9611              : 
    9612          516 :         for (i = 0; i < res_ndigits; i++)
    9613              :         {
    9614          468 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
    9615          468 :             res_digits[i] = (NumericDigit) (carry / divisor);
    9616          468 :             carry = carry % divisor;
    9617              :         }
    9618              :     }
    9619              : 
    9620              :     /* Store the quotient in result */
    9621          216 :     digitbuf_free(result->buf);
    9622          216 :     result->ndigits = res_ndigits;
    9623          216 :     result->buf = res_buf;
    9624          216 :     result->digits = res_digits;
    9625          216 :     result->weight = res_weight;
    9626          216 :     result->sign = res_sign;
    9627              : 
    9628              :     /* Round or truncate to target rscale (and set result->dscale) */
    9629          216 :     if (round)
    9630          213 :         round_var(result, rscale);
    9631              :     else
    9632            3 :         trunc_var(result, rscale);
    9633              : 
    9634              :     /* Strip leading/trailing zeroes */
    9635          216 :     strip_var(result);
    9636              : }
    9637              : #endif
    9638              : 
    9639              : 
    9640              : /*
    9641              :  * Default scale selection for division
    9642              :  *
    9643              :  * Returns the appropriate result scale for the division result.
    9644              :  */
    9645              : static int
    9646        74840 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
    9647              : {
    9648              :     int         weight1,
    9649              :                 weight2,
    9650              :                 qweight,
    9651              :                 i;
    9652              :     NumericDigit firstdigit1,
    9653              :                 firstdigit2;
    9654              :     int         rscale;
    9655              : 
    9656              :     /*
    9657              :      * The result scale of a division isn't specified in any SQL standard. For
    9658              :      * PostgreSQL we select a result scale that will give at least
    9659              :      * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
    9660              :      * result no less accurate than float8; but use a scale not less than
    9661              :      * either input's display scale.
    9662              :      */
    9663              : 
    9664              :     /* Get the actual (normalized) weight and first digit of each input */
    9665              : 
    9666        74840 :     weight1 = 0;                /* values to use if var1 is zero */
    9667        74840 :     firstdigit1 = 0;
    9668        74840 :     for (i = 0; i < var1->ndigits; i++)
    9669              :     {
    9670        73990 :         firstdigit1 = var1->digits[i];
    9671        73990 :         if (firstdigit1 != 0)
    9672              :         {
    9673        73990 :             weight1 = var1->weight - i;
    9674        73990 :             break;
    9675              :         }
    9676              :     }
    9677              : 
    9678        74840 :     weight2 = 0;                /* values to use if var2 is zero */
    9679        74840 :     firstdigit2 = 0;
    9680        74840 :     for (i = 0; i < var2->ndigits; i++)
    9681              :     {
    9682        74815 :         firstdigit2 = var2->digits[i];
    9683        74815 :         if (firstdigit2 != 0)
    9684              :         {
    9685        74815 :             weight2 = var2->weight - i;
    9686        74815 :             break;
    9687              :         }
    9688              :     }
    9689              : 
    9690              :     /*
    9691              :      * Estimate weight of quotient.  If the two first digits are equal, we
    9692              :      * can't be sure, but assume that var1 is less than var2.
    9693              :      */
    9694        74840 :     qweight = weight1 - weight2;
    9695        74840 :     if (firstdigit1 <= firstdigit2)
    9696        66424 :         qweight--;
    9697              : 
    9698              :     /* Select result scale */
    9699        74840 :     rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
    9700        74840 :     rscale = Max(rscale, var1->dscale);
    9701        74840 :     rscale = Max(rscale, var2->dscale);
    9702        74840 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
    9703        74840 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
    9704              : 
    9705        74840 :     return rscale;
    9706              : }
    9707              : 
    9708              : 
    9709              : /*
    9710              :  * mod_var() -
    9711              :  *
    9712              :  *  Calculate the modulo of two numerics at variable level
    9713              :  */
    9714              : static void
    9715       206900 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    9716              : {
    9717              :     NumericVar  tmp;
    9718              : 
    9719       206900 :     init_var(&tmp);
    9720              : 
    9721              :     /* ---------
    9722              :      * We do this using the equation
    9723              :      *      mod(x,y) = x - trunc(x/y)*y
    9724              :      * div_var can be persuaded to give us trunc(x/y) directly.
    9725              :      * ----------
    9726              :      */
    9727       206900 :     div_var(var1, var2, &tmp, 0, false, true);
    9728              : 
    9729       206900 :     mul_var(var2, &tmp, &tmp, var2->dscale);
    9730              : 
    9731       206900 :     sub_var(var1, &tmp, result);
    9732              : 
    9733       206900 :     free_var(&tmp);
    9734       206900 : }
    9735              : 
    9736              : 
    9737              : /*
    9738              :  * div_mod_var() -
    9739              :  *
    9740              :  *  Calculate the truncated integer quotient and numeric remainder of two
    9741              :  *  numeric variables.  The remainder is precise to var2's dscale.
    9742              :  */
    9743              : static void
    9744         2259 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
    9745              :             NumericVar *quot, NumericVar *rem)
    9746              : {
    9747              :     NumericVar  q;
    9748              :     NumericVar  r;
    9749              : 
    9750         2259 :     init_var(&q);
    9751         2259 :     init_var(&r);
    9752              : 
    9753              :     /*
    9754              :      * Use div_var() with exact = false to get an initial estimate for the
    9755              :      * integer quotient (truncated towards zero).  This might be slightly
    9756              :      * inaccurate, but we correct it below.
    9757              :      */
    9758         2259 :     div_var(var1, var2, &q, 0, false, false);
    9759              : 
    9760              :     /* Compute initial estimate of remainder using the quotient estimate. */
    9761         2259 :     mul_var(var2, &q, &r, var2->dscale);
    9762         2259 :     sub_var(var1, &r, &r);
    9763              : 
    9764              :     /*
    9765              :      * Adjust the results if necessary --- the remainder should have the same
    9766              :      * sign as var1, and its absolute value should be less than the absolute
    9767              :      * value of var2.
    9768              :      */
    9769         2259 :     while (r.ndigits != 0 && r.sign != var1->sign)
    9770              :     {
    9771              :         /* The absolute value of the quotient is too large */
    9772            0 :         if (var1->sign == var2->sign)
    9773              :         {
    9774            0 :             sub_var(&q, &const_one, &q);
    9775            0 :             add_var(&r, var2, &r);
    9776              :         }
    9777              :         else
    9778              :         {
    9779            0 :             add_var(&q, &const_one, &q);
    9780            0 :             sub_var(&r, var2, &r);
    9781              :         }
    9782              :     }
    9783              : 
    9784         2259 :     while (cmp_abs(&r, var2) >= 0)
    9785              :     {
    9786              :         /* The absolute value of the quotient is too small */
    9787            0 :         if (var1->sign == var2->sign)
    9788              :         {
    9789            0 :             add_var(&q, &const_one, &q);
    9790            0 :             sub_var(&r, var2, &r);
    9791              :         }
    9792              :         else
    9793              :         {
    9794            0 :             sub_var(&q, &const_one, &q);
    9795            0 :             add_var(&r, var2, &r);
    9796              :         }
    9797              :     }
    9798              : 
    9799         2259 :     set_var_from_var(&q, quot);
    9800         2259 :     set_var_from_var(&r, rem);
    9801              : 
    9802         2259 :     free_var(&q);
    9803         2259 :     free_var(&r);
    9804         2259 : }
    9805              : 
    9806              : 
    9807              : /*
    9808              :  * ceil_var() -
    9809              :  *
    9810              :  *  Return the smallest integer greater than or equal to the argument
    9811              :  *  on variable level
    9812              :  */
    9813              : static void
    9814          102 : ceil_var(const NumericVar *var, NumericVar *result)
    9815              : {
    9816              :     NumericVar  tmp;
    9817              : 
    9818          102 :     init_var(&tmp);
    9819          102 :     set_var_from_var(var, &tmp);
    9820              : 
    9821          102 :     trunc_var(&tmp, 0);
    9822              : 
    9823          102 :     if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
    9824           30 :         add_var(&tmp, &const_one, &tmp);
    9825              : 
    9826          102 :     set_var_from_var(&tmp, result);
    9827          102 :     free_var(&tmp);
    9828          102 : }
    9829              : 
    9830              : 
    9831              : /*
    9832              :  * floor_var() -
    9833              :  *
    9834              :  *  Return the largest integer equal to or less than the argument
    9835              :  *  on variable level
    9836              :  */
    9837              : static void
    9838           54 : floor_var(const NumericVar *var, NumericVar *result)
    9839              : {
    9840              :     NumericVar  tmp;
    9841              : 
    9842           54 :     init_var(&tmp);
    9843           54 :     set_var_from_var(var, &tmp);
    9844              : 
    9845           54 :     trunc_var(&tmp, 0);
    9846              : 
    9847           54 :     if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
    9848           15 :         sub_var(&tmp, &const_one, &tmp);
    9849              : 
    9850           54 :     set_var_from_var(&tmp, result);
    9851           54 :     free_var(&tmp);
    9852           54 : }
    9853              : 
    9854              : 
    9855              : /*
    9856              :  * gcd_var() -
    9857              :  *
    9858              :  *  Calculate the greatest common divisor of two numerics at variable level
    9859              :  */
    9860              : static void
    9861          111 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
    9862              : {
    9863              :     int         res_dscale;
    9864              :     int         cmp;
    9865              :     NumericVar  tmp_arg;
    9866              :     NumericVar  mod;
    9867              : 
    9868          111 :     res_dscale = Max(var1->dscale, var2->dscale);
    9869              : 
    9870              :     /*
    9871              :      * Arrange for var1 to be the number with the greater absolute value.
    9872              :      *
    9873              :      * This would happen automatically in the loop below, but avoids an
    9874              :      * expensive modulo operation.
    9875              :      */
    9876          111 :     cmp = cmp_abs(var1, var2);
    9877          111 :     if (cmp < 0)
    9878              :     {
    9879           42 :         const NumericVar *tmp = var1;
    9880              : 
    9881           42 :         var1 = var2;
    9882           42 :         var2 = tmp;
    9883              :     }
    9884              : 
    9885              :     /*
    9886              :      * Also avoid the taking the modulo if the inputs have the same absolute
    9887              :      * value, or if the smaller input is zero.
    9888              :      */
    9889          111 :     if (cmp == 0 || var2->ndigits == 0)
    9890              :     {
    9891           36 :         set_var_from_var(var1, result);
    9892           36 :         result->sign = NUMERIC_POS;
    9893           36 :         result->dscale = res_dscale;
    9894           36 :         return;
    9895              :     }
    9896              : 
    9897           75 :     init_var(&tmp_arg);
    9898           75 :     init_var(&mod);
    9899              : 
    9900              :     /* Use the Euclidean algorithm to find the GCD */
    9901           75 :     set_var_from_var(var1, &tmp_arg);
    9902           75 :     set_var_from_var(var2, result);
    9903              : 
    9904              :     for (;;)
    9905              :     {
    9906              :         /* this loop can take a while, so allow it to be interrupted */
    9907          294 :         CHECK_FOR_INTERRUPTS();
    9908              : 
    9909          294 :         mod_var(&tmp_arg, result, &mod);
    9910          294 :         if (mod.ndigits == 0)
    9911           75 :             break;
    9912          219 :         set_var_from_var(result, &tmp_arg);
    9913          219 :         set_var_from_var(&mod, result);
    9914              :     }
    9915           75 :     result->sign = NUMERIC_POS;
    9916           75 :     result->dscale = res_dscale;
    9917              : 
    9918           75 :     free_var(&tmp_arg);
    9919           75 :     free_var(&mod);
    9920              : }
    9921              : 
    9922              : 
    9923              : /*
    9924              :  * sqrt_var() -
    9925              :  *
    9926              :  *  Compute the square root of x using the Karatsuba Square Root algorithm.
    9927              :  *  NOTE: we allow rscale < 0 here, implying rounding before the decimal
    9928              :  *  point.
    9929              :  */
    9930              : static void
    9931         2097 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
    9932              : {
    9933              :     int         stat;
    9934              :     int         res_weight;
    9935              :     int         res_ndigits;
    9936              :     int         src_ndigits;
    9937              :     int         step;
    9938              :     int         ndigits[32];
    9939              :     int         blen;
    9940              :     int64       arg_int64;
    9941              :     int         src_idx;
    9942              :     int64       s_int64;
    9943              :     int64       r_int64;
    9944              :     NumericVar  s_var;
    9945              :     NumericVar  r_var;
    9946              :     NumericVar  a0_var;
    9947              :     NumericVar  a1_var;
    9948              :     NumericVar  q_var;
    9949              :     NumericVar  u_var;
    9950              : 
    9951         2097 :     stat = cmp_var(arg, &const_zero);
    9952         2097 :     if (stat == 0)
    9953              :     {
    9954            9 :         zero_var(result);
    9955            9 :         result->dscale = rscale;
    9956            9 :         return;
    9957              :     }
    9958              : 
    9959              :     /*
    9960              :      * SQL2003 defines sqrt() in terms of power, so we need to emit the right
    9961              :      * SQLSTATE error code if the operand is negative.
    9962              :      */
    9963         2088 :     if (stat < 0)
    9964            3 :         ereport(ERROR,
    9965              :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
    9966              :                  errmsg("cannot take square root of a negative number")));
    9967              : 
    9968         2085 :     init_var(&s_var);
    9969         2085 :     init_var(&r_var);
    9970         2085 :     init_var(&a0_var);
    9971         2085 :     init_var(&a1_var);
    9972         2085 :     init_var(&q_var);
    9973         2085 :     init_var(&u_var);
    9974              : 
    9975              :     /*
    9976              :      * The result weight is half the input weight, rounded towards minus
    9977              :      * infinity --- res_weight = floor(arg->weight / 2).
    9978              :      */
    9979         2085 :     if (arg->weight >= 0)
    9980         1929 :         res_weight = arg->weight / 2;
    9981              :     else
    9982          156 :         res_weight = -((-arg->weight - 1) / 2 + 1);
    9983              : 
    9984              :     /*
    9985              :      * Number of NBASE digits to compute.  To ensure correct rounding, compute
    9986              :      * at least 1 extra decimal digit.  We explicitly allow rscale to be
    9987              :      * negative here, but must always compute at least 1 NBASE digit.  Thus
    9988              :      * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
    9989              :      */
    9990         2085 :     if (rscale + 1 >= 0)
    9991         2085 :         res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
    9992              :     else
    9993            0 :         res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
    9994         2085 :     res_ndigits = Max(res_ndigits, 1);
    9995              : 
    9996              :     /*
    9997              :      * Number of source NBASE digits logically required to produce a result
    9998              :      * with this precision --- every digit before the decimal point, plus 2
    9999              :      * for each result digit after the decimal point (or minus 2 for each
   10000              :      * result digit we round before the decimal point).
   10001              :      */
   10002         2085 :     src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
   10003         2085 :     src_ndigits = Max(src_ndigits, 1);
   10004              : 
   10005              :     /* ----------
   10006              :      * From this point on, we treat the input and the result as integers and
   10007              :      * compute the integer square root and remainder using the Karatsuba
   10008              :      * Square Root algorithm, which may be written recursively as follows:
   10009              :      *
   10010              :      *  SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
   10011              :      *      [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
   10012              :      *        0 <= a0,a1,a2 < b and a3 >= b/4 ]
   10013              :      *      Let (s,r) = SqrtRem(a3*b + a2)
   10014              :      *      Let (q,u) = DivRem(r*b + a1, 2*s)
   10015              :      *      Let s = s*b + q
   10016              :      *      Let r = u*b + a0 - q^2
   10017              :      *      If r < 0 Then
   10018              :      *          Let r = r + s
   10019              :      *          Let s = s - 1
   10020              :      *          Let r = r + s
   10021              :      *      Return (s,r)
   10022              :      *
   10023              :      * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
   10024              :      * RR-3805, November 1999.  At the time of writing this was available
   10025              :      * on the net at <https://hal.inria.fr/inria-00072854>.
   10026              :      *
   10027              :      * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
   10028              :      * "choose a base b such that n requires at least four base-b digits to
   10029              :      * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
   10030              :      * than b".  For optimal performance, b should have approximately a
   10031              :      * quarter the number of digits in the input, so that the outer square
   10032              :      * root computes roughly twice as many digits as the inner one.  For
   10033              :      * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
   10034              :      *
   10035              :      * We implement the algorithm iteratively rather than recursively, to
   10036              :      * allow the working variables to be reused.  With this approach, each
   10037              :      * digit of the input is read precisely once --- src_idx tracks the number
   10038              :      * of input digits used so far.
   10039              :      *
   10040              :      * The array ndigits[] holds the number of NBASE digits of the input that
   10041              :      * will have been used at the end of each iteration, which roughly doubles
   10042              :      * each time.  Note that the array elements are stored in reverse order,
   10043              :      * so if the final iteration requires src_ndigits = 37 input digits, the
   10044              :      * array will contain [37,19,11,7,5,3], and we would start by computing
   10045              :      * the square root of the 3 most significant NBASE digits.
   10046              :      *
   10047              :      * In each iteration, we choose blen to be the largest integer for which
   10048              :      * the input number has a3 >= b/4, when written in the form above.  In
   10049              :      * general, this means blen = src_ndigits / 4 (truncated), but if
   10050              :      * src_ndigits is a multiple of 4, that might lead to the coefficient a3
   10051              :      * being less than b/4 (if the first input digit is less than NBASE/4), in
   10052              :      * which case we choose blen = src_ndigits / 4 - 1.  The number of digits
   10053              :      * in the inner square root is then src_ndigits - 2*blen.  So, for
   10054              :      * example, if we have src_ndigits = 26 initially, the array ndigits[]
   10055              :      * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
   10056              :      * the first input digit.
   10057              :      *
   10058              :      * Additionally, we can put an upper bound on the number of steps required
   10059              :      * as follows --- suppose that the number of source digits is an n-bit
   10060              :      * number in the range [2^(n-1), 2^n-1], then blen will be in the range
   10061              :      * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
   10062              :      * root will be in the range [2^(n-2), 2^(n-1)+1].  In the next step, blen
   10063              :      * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
   10064              :      * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
   10065              :      * This pattern repeats, and in the worst case the array ndigits[] will
   10066              :      * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
   10067              :      * will require n steps.  Therefore, since all digit array sizes are
   10068              :      * signed 32-bit integers, the number of steps required is guaranteed to
   10069              :      * be less than 32.
   10070              :      * ----------
   10071              :      */
   10072         2085 :     step = 0;
   10073         9981 :     while ((ndigits[step] = src_ndigits) > 4)
   10074              :     {
   10075              :         /* Choose b so that a3 >= b/4, as described above */
   10076         7896 :         blen = src_ndigits / 4;
   10077         7896 :         if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
   10078          162 :             blen--;
   10079              : 
   10080              :         /* Number of digits in the next step (inner square root) */
   10081         7896 :         src_ndigits -= 2 * blen;
   10082         7896 :         step++;
   10083              :     }
   10084              : 
   10085              :     /*
   10086              :      * First iteration (innermost square root and remainder):
   10087              :      *
   10088              :      * Here src_ndigits <= 4, and the input fits in an int64.  Its square root
   10089              :      * has at most 9 decimal digits, so estimate it using double precision
   10090              :      * arithmetic, which will in fact almost certainly return the correct
   10091              :      * result with no further correction required.
   10092              :      */
   10093         2085 :     arg_int64 = arg->digits[0];
   10094         6657 :     for (src_idx = 1; src_idx < src_ndigits; src_idx++)
   10095              :     {
   10096         4572 :         arg_int64 *= NBASE;
   10097         4572 :         if (src_idx < arg->ndigits)
   10098         3843 :             arg_int64 += arg->digits[src_idx];
   10099              :     }
   10100              : 
   10101         2085 :     s_int64 = (int64) sqrt((double) arg_int64);
   10102         2085 :     r_int64 = arg_int64 - s_int64 * s_int64;
   10103              : 
   10104              :     /*
   10105              :      * Use Newton's method to correct the result, if necessary.
   10106              :      *
   10107              :      * This uses integer division with truncation to compute the truncated
   10108              :      * integer square root by iterating using the formula x -> (x + n/x) / 2.
   10109              :      * This is known to converge to isqrt(n), unless n+1 is a perfect square.
   10110              :      * If n+1 is a perfect square, the sequence will oscillate between the two
   10111              :      * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
   10112              :      * checking the remainder.
   10113              :      */
   10114         2085 :     while (r_int64 < 0 || r_int64 > 2 * s_int64)
   10115              :     {
   10116            0 :         s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
   10117            0 :         r_int64 = arg_int64 - s_int64 * s_int64;
   10118              :     }
   10119              : 
   10120              :     /*
   10121              :      * Iterations with src_ndigits <= 8:
   10122              :      *
   10123              :      * The next 1 or 2 iterations compute larger (outer) square roots with
   10124              :      * src_ndigits <= 8, so the result still fits in an int64 (even though the
   10125              :      * input no longer does) and we can continue to compute using int64
   10126              :      * variables to avoid more expensive numeric computations.
   10127              :      *
   10128              :      * It is fairly easy to see that there is no risk of the intermediate
   10129              :      * values below overflowing 64-bit integers.  In the worst case, the
   10130              :      * previous iteration will have computed a 3-digit square root (of a
   10131              :      * 6-digit input less than NBASE^6 / 4), so at the start of this
   10132              :      * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
   10133              :      * less than 10^12.  In this case, blen will be 1, so numer will be less
   10134              :      * than 10^17, and denom will be less than 10^12 (and hence u will also be
   10135              :      * less than 10^12).  Finally, since q^2 = u*b + a0 - r, we can also be
   10136              :      * sure that q^2 < 10^17.  Therefore all these quantities fit comfortably
   10137              :      * in 64-bit integers.
   10138              :      */
   10139         2085 :     step--;
   10140         5283 :     while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
   10141              :     {
   10142              :         int         b;
   10143              :         int         a0;
   10144              :         int         a1;
   10145              :         int         i;
   10146              :         int64       numer;
   10147              :         int64       denom;
   10148              :         int64       q;
   10149              :         int64       u;
   10150              : 
   10151         3198 :         blen = (src_ndigits - src_idx) / 2;
   10152              : 
   10153              :         /* Extract a1 and a0, and compute b */
   10154         3198 :         a0 = 0;
   10155         3198 :         a1 = 0;
   10156         3198 :         b = 1;
   10157              : 
   10158         6468 :         for (i = 0; i < blen; i++, src_idx++)
   10159              :         {
   10160         3270 :             b *= NBASE;
   10161         3270 :             a1 *= NBASE;
   10162         3270 :             if (src_idx < arg->ndigits)
   10163         2400 :                 a1 += arg->digits[src_idx];
   10164              :         }
   10165              : 
   10166         6468 :         for (i = 0; i < blen; i++, src_idx++)
   10167              :         {
   10168         3270 :             a0 *= NBASE;
   10169         3270 :             if (src_idx < arg->ndigits)
   10170         2322 :                 a0 += arg->digits[src_idx];
   10171              :         }
   10172              : 
   10173              :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
   10174         3198 :         numer = r_int64 * b + a1;
   10175         3198 :         denom = 2 * s_int64;
   10176         3198 :         q = numer / denom;
   10177         3198 :         u = numer - q * denom;
   10178              : 
   10179              :         /* Compute s = s*b + q and r = u*b + a0 - q^2 */
   10180         3198 :         s_int64 = s_int64 * b + q;
   10181         3198 :         r_int64 = u * b + a0 - q * q;
   10182              : 
   10183         3198 :         if (r_int64 < 0)
   10184              :         {
   10185              :             /* s is too large by 1; set r += s, s--, r += s */
   10186          105 :             r_int64 += s_int64;
   10187          105 :             s_int64--;
   10188          105 :             r_int64 += s_int64;
   10189              :         }
   10190              : 
   10191              :         Assert(src_idx == src_ndigits); /* All input digits consumed */
   10192         3198 :         step--;
   10193              :     }
   10194              : 
   10195              :     /*
   10196              :      * On platforms with 128-bit integer support, we can further delay the
   10197              :      * need to use numeric variables.
   10198              :      */
   10199              : #ifdef HAVE_INT128
   10200         2085 :     if (step >= 0)
   10201              :     {
   10202              :         int128      s_int128;
   10203              :         int128      r_int128;
   10204              : 
   10205         2085 :         s_int128 = s_int64;
   10206         2085 :         r_int128 = r_int64;
   10207              : 
   10208              :         /*
   10209              :          * Iterations with src_ndigits <= 16:
   10210              :          *
   10211              :          * The result fits in an int128 (even though the input doesn't) so we
   10212              :          * use int128 variables to avoid more expensive numeric computations.
   10213              :          */
   10214         4524 :         while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
   10215              :         {
   10216              :             int64       b;
   10217              :             int64       a0;
   10218              :             int64       a1;
   10219              :             int64       i;
   10220              :             int128      numer;
   10221              :             int128      denom;
   10222              :             int128      q;
   10223              :             int128      u;
   10224              : 
   10225         2439 :             blen = (src_ndigits - src_idx) / 2;
   10226              : 
   10227              :             /* Extract a1 and a0, and compute b */
   10228         2439 :             a0 = 0;
   10229         2439 :             a1 = 0;
   10230         2439 :             b = 1;
   10231              : 
   10232         8040 :             for (i = 0; i < blen; i++, src_idx++)
   10233              :             {
   10234         5601 :                 b *= NBASE;
   10235         5601 :                 a1 *= NBASE;
   10236         5601 :                 if (src_idx < arg->ndigits)
   10237         3303 :                     a1 += arg->digits[src_idx];
   10238              :             }
   10239              : 
   10240         8040 :             for (i = 0; i < blen; i++, src_idx++)
   10241              :             {
   10242         5601 :                 a0 *= NBASE;
   10243         5601 :                 if (src_idx < arg->ndigits)
   10244         2235 :                     a0 += arg->digits[src_idx];
   10245              :             }
   10246              : 
   10247              :             /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
   10248         2439 :             numer = r_int128 * b + a1;
   10249         2439 :             denom = 2 * s_int128;
   10250         2439 :             q = numer / denom;
   10251         2439 :             u = numer - q * denom;
   10252              : 
   10253              :             /* Compute s = s*b + q and r = u*b + a0 - q^2 */
   10254         2439 :             s_int128 = s_int128 * b + q;
   10255         2439 :             r_int128 = u * b + a0 - q * q;
   10256              : 
   10257         2439 :             if (r_int128 < 0)
   10258              :             {
   10259              :                 /* s is too large by 1; set r += s, s--, r += s */
   10260           96 :                 r_int128 += s_int128;
   10261           96 :                 s_int128--;
   10262           96 :                 r_int128 += s_int128;
   10263              :             }
   10264              : 
   10265              :             Assert(src_idx == src_ndigits); /* All input digits consumed */
   10266         2439 :             step--;
   10267              :         }
   10268              : 
   10269              :         /*
   10270              :          * All remaining iterations require numeric variables.  Convert the
   10271              :          * integer values to NumericVar and continue.  Note that in the final
   10272              :          * iteration we don't need the remainder, so we can save a few cycles
   10273              :          * there by not fully computing it.
   10274              :          */
   10275         2085 :         int128_to_numericvar(s_int128, &s_var);
   10276         2085 :         if (step >= 0)
   10277         1362 :             int128_to_numericvar(r_int128, &r_var);
   10278              :     }
   10279              :     else
   10280              :     {
   10281            0 :         int64_to_numericvar(s_int64, &s_var);
   10282              :         /* step < 0, so we certainly don't need r */
   10283              :     }
   10284              : #else                           /* !HAVE_INT128 */
   10285              :     int64_to_numericvar(s_int64, &s_var);
   10286              :     if (step >= 0)
   10287              :         int64_to_numericvar(r_int64, &r_var);
   10288              : #endif                          /* HAVE_INT128 */
   10289              : 
   10290              :     /*
   10291              :      * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
   10292              :      * use numeric variables.
   10293              :      */
   10294         4344 :     while (step >= 0)
   10295              :     {
   10296              :         int         tmp_len;
   10297              : 
   10298         2259 :         src_ndigits = ndigits[step];
   10299         2259 :         blen = (src_ndigits - src_idx) / 2;
   10300              : 
   10301              :         /* Extract a1 and a0 */
   10302         2259 :         if (src_idx < arg->ndigits)
   10303              :         {
   10304          756 :             tmp_len = Min(blen, arg->ndigits - src_idx);
   10305          756 :             alloc_var(&a1_var, tmp_len);
   10306          756 :             memcpy(a1_var.digits, arg->digits + src_idx,
   10307              :                    tmp_len * sizeof(NumericDigit));
   10308          756 :             a1_var.weight = blen - 1;
   10309          756 :             a1_var.sign = NUMERIC_POS;
   10310          756 :             a1_var.dscale = 0;
   10311          756 :             strip_var(&a1_var);
   10312              :         }
   10313              :         else
   10314              :         {
   10315         1503 :             zero_var(&a1_var);
   10316         1503 :             a1_var.dscale = 0;
   10317              :         }
   10318         2259 :         src_idx += blen;
   10319              : 
   10320         2259 :         if (src_idx < arg->ndigits)
   10321              :         {
   10322          756 :             tmp_len = Min(blen, arg->ndigits - src_idx);
   10323          756 :             alloc_var(&a0_var, tmp_len);
   10324          756 :             memcpy(a0_var.digits, arg->digits + src_idx,
   10325              :                    tmp_len * sizeof(NumericDigit));
   10326          756 :             a0_var.weight = blen - 1;
   10327          756 :             a0_var.sign = NUMERIC_POS;
   10328          756 :             a0_var.dscale = 0;
   10329          756 :             strip_var(&a0_var);
   10330              :         }
   10331              :         else
   10332              :         {
   10333         1503 :             zero_var(&a0_var);
   10334         1503 :             a0_var.dscale = 0;
   10335              :         }
   10336         2259 :         src_idx += blen;
   10337              : 
   10338              :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
   10339         2259 :         set_var_from_var(&r_var, &q_var);
   10340         2259 :         q_var.weight += blen;
   10341         2259 :         add_var(&q_var, &a1_var, &q_var);
   10342         2259 :         add_var(&s_var, &s_var, &u_var);
   10343         2259 :         div_mod_var(&q_var, &u_var, &q_var, &u_var);
   10344              : 
   10345              :         /* Compute s = s*b + q */
   10346         2259 :         s_var.weight += blen;
   10347         2259 :         add_var(&s_var, &q_var, &s_var);
   10348              : 
   10349              :         /*
   10350              :          * Compute r = u*b + a0 - q^2.
   10351              :          *
   10352              :          * In the final iteration, we don't actually need r; we just need to
   10353              :          * know whether it is negative, so that we know whether to adjust s.
   10354              :          * So instead of the final subtraction we can just compare.
   10355              :          */
   10356         2259 :         u_var.weight += blen;
   10357         2259 :         add_var(&u_var, &a0_var, &u_var);
   10358         2259 :         mul_var(&q_var, &q_var, &q_var, 0);
   10359              : 
   10360         2259 :         if (step > 0)
   10361              :         {
   10362              :             /* Need r for later iterations */
   10363          897 :             sub_var(&u_var, &q_var, &r_var);
   10364          897 :             if (r_var.sign == NUMERIC_NEG)
   10365              :             {
   10366              :                 /* s is too large by 1; set r += s, s--, r += s */
   10367           60 :                 add_var(&r_var, &s_var, &r_var);
   10368           60 :                 sub_var(&s_var, &const_one, &s_var);
   10369           60 :                 add_var(&r_var, &s_var, &r_var);
   10370              :             }
   10371              :         }
   10372              :         else
   10373              :         {
   10374              :             /* Don't need r anymore, except to test if s is too large by 1 */
   10375         1362 :             if (cmp_var(&u_var, &q_var) < 0)
   10376           18 :                 sub_var(&s_var, &const_one, &s_var);
   10377              :         }
   10378              : 
   10379              :         Assert(src_idx == src_ndigits); /* All input digits consumed */
   10380         2259 :         step--;
   10381              :     }
   10382              : 
   10383              :     /*
   10384              :      * Construct the final result, rounding it to the requested precision.
   10385              :      */
   10386         2085 :     set_var_from_var(&s_var, result);
   10387         2085 :     result->weight = res_weight;
   10388         2085 :     result->sign = NUMERIC_POS;
   10389              : 
   10390              :     /* Round to target rscale (and set result->dscale) */
   10391         2085 :     round_var(result, rscale);
   10392              : 
   10393              :     /* Strip leading and trailing zeroes */
   10394         2085 :     strip_var(result);
   10395              : 
   10396         2085 :     free_var(&s_var);
   10397         2085 :     free_var(&r_var);
   10398         2085 :     free_var(&a0_var);
   10399         2085 :     free_var(&a1_var);
   10400         2085 :     free_var(&q_var);
   10401         2085 :     free_var(&u_var);
   10402              : }
   10403              : 
   10404              : 
   10405              : /*
   10406              :  * exp_var() -
   10407              :  *
   10408              :  *  Raise e to the power of x, computed to rscale fractional digits
   10409              :  */
   10410              : static void
   10411           90 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
   10412              : {
   10413              :     NumericVar  x;
   10414              :     NumericVar  elem;
   10415              :     int         ni;
   10416              :     double      val;
   10417              :     int         dweight;
   10418              :     int         ndiv2;
   10419              :     int         sig_digits;
   10420              :     int         local_rscale;
   10421              : 
   10422           90 :     init_var(&x);
   10423           90 :     init_var(&elem);
   10424              : 
   10425           90 :     set_var_from_var(arg, &x);
   10426              : 
   10427              :     /*
   10428              :      * Estimate the dweight of the result using floating point arithmetic, so
   10429              :      * that we can choose an appropriate local rscale for the calculation.
   10430              :      */
   10431           90 :     val = numericvar_to_double_no_overflow(&x);
   10432              : 
   10433              :     /* Guard against overflow/underflow */
   10434              :     /* If you change this limit, see also power_var()'s limit */
   10435           90 :     if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
   10436              :     {
   10437            3 :         if (val > 0)
   10438            0 :             ereport(ERROR,
   10439              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
   10440              :                      errmsg("value overflows numeric format")));
   10441            3 :         zero_var(result);
   10442            3 :         result->dscale = rscale;
   10443            3 :         return;
   10444              :     }
   10445              : 
   10446              :     /* decimal weight = log10(e^x) = x * log10(e) */
   10447           87 :     dweight = (int) (val * 0.434294481903252);
   10448              : 
   10449              :     /*
   10450              :      * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
   10451              :      * 2^ndiv2, to improve the convergence rate of the Taylor series.
   10452              :      *
   10453              :      * Note that the overflow check above ensures that fabs(x) < 6000, which
   10454              :      * means that ndiv2 <= 20 here.
   10455              :      */
   10456           87 :     if (fabs(val) > 0.01)
   10457              :     {
   10458           72 :         ndiv2 = 1;
   10459           72 :         val /= 2;
   10460              : 
   10461          909 :         while (fabs(val) > 0.01)
   10462              :         {
   10463          837 :             ndiv2++;
   10464          837 :             val /= 2;
   10465              :         }
   10466              : 
   10467           72 :         local_rscale = x.dscale + ndiv2;
   10468           72 :         div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
   10469              :     }
   10470              :     else
   10471           15 :         ndiv2 = 0;
   10472              : 
   10473              :     /*
   10474              :      * Set the scale for the Taylor series expansion.  The final result has
   10475              :      * (dweight + rscale + 1) significant digits.  In addition, we have to
   10476              :      * raise the Taylor series result to the power 2^ndiv2, which introduces
   10477              :      * an error of up to around log10(2^ndiv2) digits, so work with this many
   10478              :      * extra digits of precision (plus a few more for good measure).
   10479              :      */
   10480           87 :     sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
   10481           87 :     sig_digits = Max(sig_digits, 0) + 8;
   10482              : 
   10483           87 :     local_rscale = sig_digits - 1;
   10484              : 
   10485              :     /*
   10486              :      * Use the Taylor series
   10487              :      *
   10488              :      * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
   10489              :      *
   10490              :      * Given the limited range of x, this should converge reasonably quickly.
   10491              :      * We run the series until the terms fall below the local_rscale limit.
   10492              :      */
   10493           87 :     add_var(&const_one, &x, result);
   10494              : 
   10495           87 :     mul_var(&x, &x, &elem, local_rscale);
   10496           87 :     ni = 2;
   10497           87 :     div_var_int(&elem, ni, 0, &elem, local_rscale, true);
   10498              : 
   10499         2496 :     while (elem.ndigits != 0)
   10500              :     {
   10501         2409 :         add_var(result, &elem, result);
   10502              : 
   10503         2409 :         mul_var(&elem, &x, &elem, local_rscale);
   10504         2409 :         ni++;
   10505         2409 :         div_var_int(&elem, ni, 0, &elem, local_rscale, true);
   10506              :     }
   10507              : 
   10508              :     /*
   10509              :      * Compensate for the argument range reduction.  Since the weight of the
   10510              :      * result doubles with each multiplication, we can reduce the local rscale
   10511              :      * as we proceed.
   10512              :      */
   10513          996 :     while (ndiv2-- > 0)
   10514              :     {
   10515          909 :         local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
   10516          909 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10517          909 :         mul_var(result, result, result, local_rscale);
   10518              :     }
   10519              : 
   10520              :     /* Round to requested rscale */
   10521           87 :     round_var(result, rscale);
   10522              : 
   10523           87 :     free_var(&x);
   10524           87 :     free_var(&elem);
   10525              : }
   10526              : 
   10527              : 
   10528              : /*
   10529              :  * Estimate the dweight of the most significant decimal digit of the natural
   10530              :  * logarithm of a number.
   10531              :  *
   10532              :  * Essentially, we're approximating log10(abs(ln(var))).  This is used to
   10533              :  * determine the appropriate rscale when computing natural logarithms.
   10534              :  *
   10535              :  * Note: many callers call this before range-checking the input.  Therefore,
   10536              :  * we must be robust against values that are invalid to apply ln() to.
   10537              :  * We don't wish to throw an error here, so just return zero in such cases.
   10538              :  */
   10539              : static int
   10540          369 : estimate_ln_dweight(const NumericVar *var)
   10541              : {
   10542              :     int         ln_dweight;
   10543              : 
   10544              :     /* Caller should fail on ln(negative), but for the moment return zero */
   10545          369 :     if (var->sign != NUMERIC_POS)
   10546           21 :         return 0;
   10547              : 
   10548          657 :     if (cmp_var(var, &const_zero_point_nine) >= 0 &&
   10549          309 :         cmp_var(var, &const_one_point_one) <= 0)
   10550           45 :     {
   10551              :         /*
   10552              :          * 0.9 <= var <= 1.1
   10553              :          *
   10554              :          * ln(var) has a negative weight (possibly very large).  To get a
   10555              :          * reasonably accurate result, estimate it using ln(1+x) ~= x.
   10556              :          */
   10557              :         NumericVar  x;
   10558              : 
   10559           45 :         init_var(&x);
   10560           45 :         sub_var(var, &const_one, &x);
   10561              : 
   10562           45 :         if (x.ndigits > 0)
   10563              :         {
   10564              :             /* Use weight of most significant decimal digit of x */
   10565           21 :             ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
   10566              :         }
   10567              :         else
   10568              :         {
   10569              :             /* x = 0.  Since ln(1) = 0 exactly, we don't need extra digits */
   10570           24 :             ln_dweight = 0;
   10571              :         }
   10572              : 
   10573           45 :         free_var(&x);
   10574              :     }
   10575              :     else
   10576              :     {
   10577              :         /*
   10578              :          * Estimate the logarithm using the first couple of digits from the
   10579              :          * input number.  This will give an accurate result whenever the input
   10580              :          * is not too close to 1.
   10581              :          */
   10582          303 :         if (var->ndigits > 0)
   10583              :         {
   10584              :             int         digits;
   10585              :             int         dweight;
   10586              :             double      ln_var;
   10587              : 
   10588          282 :             digits = var->digits[0];
   10589          282 :             dweight = var->weight * DEC_DIGITS;
   10590              : 
   10591          282 :             if (var->ndigits > 1)
   10592              :             {
   10593          171 :                 digits = digits * NBASE + var->digits[1];
   10594          171 :                 dweight -= DEC_DIGITS;
   10595              :             }
   10596              : 
   10597              :             /*----------
   10598              :              * We have var ~= digits * 10^dweight
   10599              :              * so ln(var) ~= ln(digits) + dweight * ln(10)
   10600              :              *----------
   10601              :              */
   10602          282 :             ln_var = log((double) digits) + dweight * 2.302585092994046;
   10603          282 :             ln_dweight = (int) log10(fabs(ln_var));
   10604              :         }
   10605              :         else
   10606              :         {
   10607              :             /* Caller should fail on ln(0), but for the moment return zero */
   10608           21 :             ln_dweight = 0;
   10609              :         }
   10610              :     }
   10611              : 
   10612          348 :     return ln_dweight;
   10613              : }
   10614              : 
   10615              : 
   10616              : /*
   10617              :  * ln_var() -
   10618              :  *
   10619              :  *  Compute the natural log of x
   10620              :  */
   10621              : static void
   10622          417 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
   10623              : {
   10624              :     NumericVar  x;
   10625              :     NumericVar  xx;
   10626              :     int         ni;
   10627              :     NumericVar  elem;
   10628              :     NumericVar  fact;
   10629              :     int         nsqrt;
   10630              :     int         local_rscale;
   10631              :     int         cmp;
   10632              : 
   10633          417 :     cmp = cmp_var(arg, &const_zero);
   10634          417 :     if (cmp == 0)
   10635           21 :         ereport(ERROR,
   10636              :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
   10637              :                  errmsg("cannot take logarithm of zero")));
   10638          396 :     else if (cmp < 0)
   10639           18 :         ereport(ERROR,
   10640              :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
   10641              :                  errmsg("cannot take logarithm of a negative number")));
   10642              : 
   10643          378 :     init_var(&x);
   10644          378 :     init_var(&xx);
   10645          378 :     init_var(&elem);
   10646          378 :     init_var(&fact);
   10647              : 
   10648          378 :     set_var_from_var(arg, &x);
   10649          378 :     set_var_from_var(&const_two, &fact);
   10650              : 
   10651              :     /*
   10652              :      * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
   10653              :      *
   10654              :      * The final logarithm will have up to around rscale+6 significant digits.
   10655              :      * Each sqrt() will roughly halve the weight of x, so adjust the local
   10656              :      * rscale as we work so that we keep this many significant digits at each
   10657              :      * step (plus a few more for good measure).
   10658              :      *
   10659              :      * Note that we allow local_rscale < 0 during this input reduction
   10660              :      * process, which implies rounding before the decimal point.  sqrt_var()
   10661              :      * explicitly supports this, and it significantly reduces the work
   10662              :      * required to reduce very large inputs to the required range.  Once the
   10663              :      * input reduction is complete, x.weight will be 0 and its display scale
   10664              :      * will be non-negative again.
   10665              :      */
   10666          378 :     nsqrt = 0;
   10667          534 :     while (cmp_var(&x, &const_zero_point_nine) <= 0)
   10668              :     {
   10669          156 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
   10670          156 :         sqrt_var(&x, &x, local_rscale);
   10671          156 :         mul_var(&fact, &const_two, &fact, 0);
   10672          156 :         nsqrt++;
   10673              :     }
   10674         2064 :     while (cmp_var(&x, &const_one_point_one) >= 0)
   10675              :     {
   10676         1686 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
   10677         1686 :         sqrt_var(&x, &x, local_rscale);
   10678         1686 :         mul_var(&fact, &const_two, &fact, 0);
   10679         1686 :         nsqrt++;
   10680              :     }
   10681              : 
   10682              :     /*
   10683              :      * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
   10684              :      *
   10685              :      * z + z^3/3 + z^5/5 + ...
   10686              :      *
   10687              :      * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
   10688              :      * due to the above range-reduction of x.
   10689              :      *
   10690              :      * The convergence of this is not as fast as one would like, but is
   10691              :      * tolerable given that z is small.
   10692              :      *
   10693              :      * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
   10694              :      * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
   10695              :      * digits of precision (plus a few more for good measure).
   10696              :      */
   10697          378 :     local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
   10698              : 
   10699          378 :     sub_var(&x, &const_one, result);
   10700          378 :     add_var(&x, &const_one, &elem);
   10701          378 :     div_var(result, &elem, result, local_rscale, true, false);
   10702          378 :     set_var_from_var(result, &xx);
   10703          378 :     mul_var(result, result, &x, local_rscale);
   10704              : 
   10705          378 :     ni = 1;
   10706              : 
   10707              :     for (;;)
   10708              :     {
   10709         7011 :         ni += 2;
   10710         7011 :         mul_var(&xx, &x, &xx, local_rscale);
   10711         7011 :         div_var_int(&xx, ni, 0, &elem, local_rscale, true);
   10712              : 
   10713         7011 :         if (elem.ndigits == 0)
   10714          378 :             break;
   10715              : 
   10716         6633 :         add_var(result, &elem, result);
   10717              : 
   10718         6633 :         if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
   10719            0 :             break;
   10720              :     }
   10721              : 
   10722              :     /* Compensate for argument range reduction, round to requested rscale */
   10723          378 :     mul_var(result, &fact, result, rscale);
   10724              : 
   10725          378 :     free_var(&x);
   10726          378 :     free_var(&xx);
   10727          378 :     free_var(&elem);
   10728          378 :     free_var(&fact);
   10729          378 : }
   10730              : 
   10731              : 
   10732              : /*
   10733              :  * log_var() -
   10734              :  *
   10735              :  *  Compute the logarithm of num in a given base.
   10736              :  *
   10737              :  *  Note: this routine chooses dscale of the result.
   10738              :  */
   10739              : static void
   10740          108 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
   10741              : {
   10742              :     NumericVar  ln_base;
   10743              :     NumericVar  ln_num;
   10744              :     int         ln_base_dweight;
   10745              :     int         ln_num_dweight;
   10746              :     int         result_dweight;
   10747              :     int         rscale;
   10748              :     int         ln_base_rscale;
   10749              :     int         ln_num_rscale;
   10750              : 
   10751          108 :     init_var(&ln_base);
   10752          108 :     init_var(&ln_num);
   10753              : 
   10754              :     /* Estimated dweights of ln(base), ln(num) and the final result */
   10755          108 :     ln_base_dweight = estimate_ln_dweight(base);
   10756          108 :     ln_num_dweight = estimate_ln_dweight(num);
   10757          108 :     result_dweight = ln_num_dweight - ln_base_dweight;
   10758              : 
   10759              :     /*
   10760              :      * Select the scale of the result so that it will have at least
   10761              :      * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
   10762              :      * input's display scale.
   10763              :      */
   10764          108 :     rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
   10765          108 :     rscale = Max(rscale, base->dscale);
   10766          108 :     rscale = Max(rscale, num->dscale);
   10767          108 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10768          108 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
   10769              : 
   10770              :     /*
   10771              :      * Set the scales for ln(base) and ln(num) so that they each have more
   10772              :      * significant digits than the final result.
   10773              :      */
   10774          108 :     ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
   10775          108 :     ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10776              : 
   10777          108 :     ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
   10778          108 :     ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10779              : 
   10780              :     /* Form natural logarithms */
   10781          108 :     ln_var(base, &ln_base, ln_base_rscale);
   10782           96 :     ln_var(num, &ln_num, ln_num_rscale);
   10783              : 
   10784              :     /* Divide and round to the required scale */
   10785           81 :     div_var(&ln_num, &ln_base, result, rscale, true, false);
   10786              : 
   10787           78 :     free_var(&ln_num);
   10788           78 :     free_var(&ln_base);
   10789           78 : }
   10790              : 
   10791              : 
   10792              : /*
   10793              :  * power_var() -
   10794              :  *
   10795              :  *  Raise base to the power of exp
   10796              :  *
   10797              :  *  Note: this routine chooses dscale of the result.
   10798              :  */
   10799              : static void
   10800          699 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
   10801              : {
   10802              :     int         res_sign;
   10803              :     NumericVar  abs_base;
   10804              :     NumericVar  ln_base;
   10805              :     NumericVar  ln_num;
   10806              :     int         ln_dweight;
   10807              :     int         rscale;
   10808              :     int         sig_digits;
   10809              :     int         local_rscale;
   10810              :     double      val;
   10811              : 
   10812              :     /* If exp can be represented as an integer, use power_var_int */
   10813          699 :     if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
   10814              :     {
   10815              :         /* exact integer, but does it fit in int? */
   10816              :         int64       expval64;
   10817              : 
   10818          636 :         if (numericvar_to_int64(exp, &expval64))
   10819              :         {
   10820          633 :             if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
   10821              :             {
   10822              :                 /* Okay, use power_var_int */
   10823          618 :                 power_var_int(base, (int) expval64, exp->dscale, result);
   10824          612 :                 return;
   10825              :             }
   10826              :         }
   10827              :     }
   10828              : 
   10829              :     /*
   10830              :      * This avoids log(0) for cases of 0 raised to a non-integer.  0 ^ 0 is
   10831              :      * handled by power_var_int().
   10832              :      */
   10833           81 :     if (cmp_var(base, &const_zero) == 0)
   10834              :     {
   10835            9 :         set_var_from_var(&const_zero, result);
   10836            9 :         result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
   10837            9 :         return;
   10838              :     }
   10839              : 
   10840           72 :     init_var(&abs_base);
   10841           72 :     init_var(&ln_base);
   10842           72 :     init_var(&ln_num);
   10843              : 
   10844              :     /*
   10845              :      * If base is negative, insist that exp be an integer.  The result is then
   10846              :      * positive if exp is even and negative if exp is odd.
   10847              :      */
   10848           72 :     if (base->sign == NUMERIC_NEG)
   10849              :     {
   10850              :         /*
   10851              :          * Check that exp is an integer.  This error code is defined by the
   10852              :          * SQL standard, and matches other errors in numeric_power().
   10853              :          */
   10854           18 :         if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
   10855            9 :             ereport(ERROR,
   10856              :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
   10857              :                      errmsg("a negative number raised to a non-integer power yields a complex result")));
   10858              : 
   10859              :         /* Test if exp is odd or even */
   10860            9 :         if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
   10861            6 :             (exp->digits[exp->ndigits - 1] & 1))
   10862            3 :             res_sign = NUMERIC_NEG;
   10863              :         else
   10864            6 :             res_sign = NUMERIC_POS;
   10865              : 
   10866              :         /* Then work with abs(base) below */
   10867            9 :         set_var_from_var(base, &abs_base);
   10868            9 :         abs_base.sign = NUMERIC_POS;
   10869            9 :         base = &abs_base;
   10870              :     }
   10871              :     else
   10872           54 :         res_sign = NUMERIC_POS;
   10873              : 
   10874              :     /*----------
   10875              :      * Decide on the scale for the ln() calculation.  For this we need an
   10876              :      * estimate of the weight of the result, which we obtain by doing an
   10877              :      * initial low-precision calculation of exp * ln(base).
   10878              :      *
   10879              :      * We want result = e ^ (exp * ln(base))
   10880              :      * so result dweight = log10(result) = exp * ln(base) * log10(e)
   10881              :      *
   10882              :      * We also perform a crude overflow test here so that we can exit early if
   10883              :      * the full-precision result is sure to overflow, and to guard against
   10884              :      * integer overflow when determining the scale for the real calculation.
   10885              :      * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
   10886              :      * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
   10887              :      * Since the values here are only approximations, we apply a small fuzz
   10888              :      * factor to this overflow test and let exp_var() determine the exact
   10889              :      * overflow threshold so that it is consistent for all inputs.
   10890              :      *----------
   10891              :      */
   10892           63 :     ln_dweight = estimate_ln_dweight(base);
   10893              : 
   10894              :     /*
   10895              :      * Set the scale for the low-precision calculation, computing ln(base) to
   10896              :      * around 8 significant digits.  Note that ln_dweight may be as small as
   10897              :      * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
   10898              :      * here.
   10899              :      */
   10900           63 :     local_rscale = 8 - ln_dweight;
   10901           63 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10902              : 
   10903           63 :     ln_var(base, &ln_base, local_rscale);
   10904              : 
   10905           63 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
   10906              : 
   10907           63 :     val = numericvar_to_double_no_overflow(&ln_num);
   10908              : 
   10909              :     /* initial overflow/underflow test with fuzz factor */
   10910           63 :     if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
   10911              :     {
   10912            3 :         if (val > 0)
   10913            0 :             ereport(ERROR,
   10914              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
   10915              :                      errmsg("value overflows numeric format")));
   10916            3 :         zero_var(result);
   10917            3 :         result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
   10918            3 :         return;
   10919              :     }
   10920              : 
   10921           60 :     val *= 0.434294481903252;   /* approximate decimal result weight */
   10922              : 
   10923              :     /* choose the result scale */
   10924           60 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
   10925           60 :     rscale = Max(rscale, base->dscale);
   10926           60 :     rscale = Max(rscale, exp->dscale);
   10927           60 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10928           60 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
   10929              : 
   10930              :     /* significant digits required in the result */
   10931           60 :     sig_digits = rscale + (int) val;
   10932           60 :     sig_digits = Max(sig_digits, 0);
   10933              : 
   10934              :     /* set the scale for the real exp * ln(base) calculation */
   10935           60 :     local_rscale = sig_digits - ln_dweight + 8;
   10936           60 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   10937              : 
   10938              :     /* and do the real calculation */
   10939              : 
   10940           60 :     ln_var(base, &ln_base, local_rscale);
   10941              : 
   10942           60 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
   10943              : 
   10944           60 :     exp_var(&ln_num, result, rscale);
   10945              : 
   10946           60 :     if (res_sign == NUMERIC_NEG && result->ndigits > 0)
   10947            3 :         result->sign = NUMERIC_NEG;
   10948              : 
   10949           60 :     free_var(&ln_num);
   10950           60 :     free_var(&ln_base);
   10951           60 :     free_var(&abs_base);
   10952              : }
   10953              : 
   10954              : /*
   10955              :  * power_var_int() -
   10956              :  *
   10957              :  *  Raise base to the power of exp, where exp is an integer.
   10958              :  *
   10959              :  *  Note: this routine chooses dscale of the result.
   10960              :  */
   10961              : static void
   10962          618 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
   10963              :               NumericVar *result)
   10964              : {
   10965              :     double      f;
   10966              :     int         p;
   10967              :     int         i;
   10968              :     int         rscale;
   10969              :     int         sig_digits;
   10970              :     unsigned int mask;
   10971              :     bool        neg;
   10972              :     NumericVar  base_prod;
   10973              :     int         local_rscale;
   10974              : 
   10975              :     /*
   10976              :      * Choose the result scale.  For this we need an estimate of the decimal
   10977              :      * weight of the result, which we obtain by approximating using double
   10978              :      * precision arithmetic.
   10979              :      *
   10980              :      * We also perform crude overflow/underflow tests here so that we can exit
   10981              :      * early if the result is sure to overflow/underflow, and to guard against
   10982              :      * integer overflow when choosing the result scale.
   10983              :      */
   10984          618 :     if (base->ndigits != 0)
   10985              :     {
   10986              :         /*----------
   10987              :          * Choose f (double) and p (int) such that base ~= f * 10^p.
   10988              :          * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
   10989              :          *----------
   10990              :          */
   10991          603 :         f = base->digits[0];
   10992          603 :         p = base->weight * DEC_DIGITS;
   10993              : 
   10994          645 :         for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
   10995              :         {
   10996           42 :             f = f * NBASE + base->digits[i];
   10997           42 :             p -= DEC_DIGITS;
   10998              :         }
   10999              : 
   11000          603 :         f = exp * (log10(f) + p);   /* approximate decimal result weight */
   11001              :     }
   11002              :     else
   11003           15 :         f = 0;                  /* result is 0 or 1 (weight 0), or error */
   11004              : 
   11005              :     /* overflow/underflow tests with fuzz factors */
   11006          618 :     if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
   11007            6 :         ereport(ERROR,
   11008              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
   11009              :                  errmsg("value overflows numeric format")));
   11010          612 :     if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
   11011              :     {
   11012            6 :         zero_var(result);
   11013            6 :         result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
   11014          108 :         return;
   11015              :     }
   11016              : 
   11017              :     /*
   11018              :      * Choose the result scale in the same way as power_var(), so it has at
   11019              :      * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
   11020              :      * either input's display scale.
   11021              :      */
   11022          606 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
   11023          606 :     rscale = Max(rscale, base->dscale);
   11024          606 :     rscale = Max(rscale, exp_dscale);
   11025          606 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
   11026          606 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
   11027              : 
   11028              :     /* Handle some common special cases, as well as corner cases */
   11029          606 :     switch (exp)
   11030              :     {
   11031           36 :         case 0:
   11032              : 
   11033              :             /*
   11034              :              * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
   11035              :              * it as 1 because most programming languages do this. SQL:2003
   11036              :              * also requires a return value of 1.
   11037              :              * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
   11038              :              */
   11039           36 :             set_var_from_var(&const_one, result);
   11040           36 :             result->dscale = rscale; /* no need to round */
   11041           36 :             return;
   11042           24 :         case 1:
   11043           24 :             set_var_from_var(base, result);
   11044           24 :             round_var(result, rscale);
   11045           24 :             return;
   11046           15 :         case -1:
   11047           15 :             div_var(&const_one, base, result, rscale, true, true);
   11048           15 :             return;
   11049           27 :         case 2:
   11050           27 :             mul_var(base, base, result, rscale);
   11051           27 :             return;
   11052          504 :         default:
   11053          504 :             break;
   11054              :     }
   11055              : 
   11056              :     /* Handle the special case where the base is zero */
   11057          504 :     if (base->ndigits == 0)
   11058              :     {
   11059            0 :         if (exp < 0)
   11060            0 :             ereport(ERROR,
   11061              :                     (errcode(ERRCODE_DIVISION_BY_ZERO),
   11062              :                      errmsg("division by zero")));
   11063            0 :         zero_var(result);
   11064            0 :         result->dscale = rscale;
   11065            0 :         return;
   11066              :     }
   11067              : 
   11068              :     /*
   11069              :      * The general case repeatedly multiplies base according to the bit
   11070              :      * pattern of exp.
   11071              :      *
   11072              :      * The local rscale used for each multiplication is varied to keep a fixed
   11073              :      * number of significant digits, sufficient to give the required result
   11074              :      * scale.
   11075              :      */
   11076              : 
   11077              :     /*
   11078              :      * Approximate number of significant digits in the result.  Note that the
   11079              :      * underflow test above, together with the choice of rscale, ensures that
   11080              :      * this approximation is necessarily > 0.
   11081              :      */
   11082          504 :     sig_digits = 1 + rscale + (int) f;
   11083              : 
   11084              :     /*
   11085              :      * The multiplications to produce the result may introduce an error of up
   11086              :      * to around log10(abs(exp)) digits, so work with this many extra digits
   11087              :      * of precision (plus a few more for good measure).
   11088              :      */
   11089          504 :     sig_digits += (int) log(fabs((double) exp)) + 8;
   11090              : 
   11091              :     /*
   11092              :      * Now we can proceed with the multiplications.
   11093              :      */
   11094          504 :     neg = (exp < 0);
   11095          504 :     mask = pg_abs_s32(exp);
   11096              : 
   11097          504 :     init_var(&base_prod);
   11098          504 :     set_var_from_var(base, &base_prod);
   11099              : 
   11100          504 :     if (mask & 1)
   11101          249 :         set_var_from_var(base, result);
   11102              :     else
   11103          255 :         set_var_from_var(&const_one, result);
   11104              : 
   11105         2538 :     while ((mask >>= 1) > 0)
   11106              :     {
   11107              :         /*
   11108              :          * Do the multiplications using rscales large enough to hold the
   11109              :          * results to the required number of significant digits, but don't
   11110              :          * waste time by exceeding the scales of the numbers themselves.
   11111              :          */
   11112         2034 :         local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
   11113         2034 :         local_rscale = Min(local_rscale, 2 * base_prod.dscale);
   11114         2034 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   11115              : 
   11116         2034 :         mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
   11117              : 
   11118         2034 :         if (mask & 1)
   11119              :         {
   11120         1329 :             local_rscale = sig_digits -
   11121         1329 :                 (base_prod.weight + result->weight) * DEC_DIGITS;
   11122         1329 :             local_rscale = Min(local_rscale,
   11123              :                                base_prod.dscale + result->dscale);
   11124         1329 :             local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
   11125              : 
   11126         1329 :             mul_var(&base_prod, result, result, local_rscale);
   11127              :         }
   11128              : 
   11129              :         /*
   11130              :          * When abs(base) > 1, the number of digits to the left of the decimal
   11131              :          * point in base_prod doubles at each iteration, so if exp is large we
   11132              :          * could easily spend large amounts of time and memory space doing the
   11133              :          * multiplications.  But once the weight exceeds what will fit in
   11134              :          * int16, the final result is guaranteed to overflow (or underflow, if
   11135              :          * exp < 0), so we can give up before wasting too many cycles.
   11136              :          */
   11137         2034 :         if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
   11138         2034 :             result->weight > NUMERIC_WEIGHT_MAX)
   11139              :         {
   11140              :             /* overflow, unless neg, in which case result should be 0 */
   11141            0 :             if (!neg)
   11142            0 :                 ereport(ERROR,
   11143              :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
   11144              :                          errmsg("value overflows numeric format")));
   11145            0 :             zero_var(result);
   11146            0 :             neg = false;
   11147            0 :             break;
   11148              :         }
   11149              :     }
   11150              : 
   11151          504 :     free_var(&base_prod);
   11152              : 
   11153              :     /* Compensate for input sign, and round to requested rscale */
   11154          504 :     if (neg)
   11155          243 :         div_var(&const_one, result, result, rscale, true, false);
   11156              :     else
   11157          261 :         round_var(result, rscale);
   11158              : }
   11159              : 
   11160              : /*
   11161              :  * power_ten_int() -
   11162              :  *
   11163              :  *  Raise ten to the power of exp, where exp is an integer.  Note that unlike
   11164              :  *  power_var_int(), this does no overflow/underflow checking or rounding.
   11165              :  */
   11166              : static void
   11167          114 : power_ten_int(int exp, NumericVar *result)
   11168              : {
   11169              :     /* Construct the result directly, starting from 10^0 = 1 */
   11170          114 :     set_var_from_var(&const_one, result);
   11171              : 
   11172              :     /* Scale needed to represent the result exactly */
   11173          114 :     result->dscale = exp < 0 ? -exp : 0;
   11174              : 
   11175              :     /* Base-NBASE weight of result and remaining exponent */
   11176          114 :     if (exp >= 0)
   11177           81 :         result->weight = exp / DEC_DIGITS;
   11178              :     else
   11179           33 :         result->weight = (exp + 1) / DEC_DIGITS - 1;
   11180              : 
   11181          114 :     exp -= result->weight * DEC_DIGITS;
   11182              : 
   11183              :     /* Final adjustment of the result's single NBASE digit */
   11184          297 :     while (exp-- > 0)
   11185          183 :         result->digits[0] *= 10;
   11186          114 : }
   11187              : 
   11188              : /*
   11189              :  * random_var() - return a random value in the range [rmin, rmax].
   11190              :  */
   11191              : static void
   11192        16719 : random_var(pg_prng_state *state, const NumericVar *rmin,
   11193              :            const NumericVar *rmax, NumericVar *result)
   11194              : {
   11195              :     int         rscale;
   11196              :     NumericVar  rlen;
   11197              :     int         res_ndigits;
   11198              :     int         n;
   11199              :     int         pow10;
   11200              :     int         i;
   11201              :     uint64      rlen64;
   11202              :     int         rlen64_ndigits;
   11203              : 
   11204        16719 :     rscale = Max(rmin->dscale, rmax->dscale);
   11205              : 
   11206              :     /* Compute rlen = rmax - rmin and check the range bounds */
   11207        16719 :     init_var(&rlen);
   11208        16719 :     sub_var(rmax, rmin, &rlen);
   11209              : 
   11210        16719 :     if (rlen.sign == NUMERIC_NEG)
   11211            3 :         ereport(ERROR,
   11212              :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
   11213              :                 errmsg("lower bound must be less than or equal to upper bound"));
   11214              : 
   11215              :     /* Special case for an empty range */
   11216        16716 :     if (rlen.ndigits == 0)
   11217              :     {
   11218            6 :         set_var_from_var(rmin, result);
   11219            6 :         result->dscale = rscale;
   11220            6 :         free_var(&rlen);
   11221            6 :         return;
   11222              :     }
   11223              : 
   11224              :     /*
   11225              :      * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
   11226              :      * and shift it to the required range by adding rmin.
   11227              :      */
   11228              : 
   11229              :     /* Required result digits */
   11230        16710 :     res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
   11231              : 
   11232              :     /*
   11233              :      * To get the required rscale, the final result digit must be a multiple
   11234              :      * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
   11235              :      */
   11236        16710 :     n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
   11237        16710 :     pow10 = 1;
   11238        43950 :     for (i = 0; i < n; i++)
   11239        27240 :         pow10 *= 10;
   11240              : 
   11241              :     /*
   11242              :      * To choose a random value uniformly from the range [0, rlen], we choose
   11243              :      * from the slightly larger range [0, rlen2], where rlen2 is formed from
   11244              :      * rlen by copying the first 4 NBASE digits, and setting all remaining
   11245              :      * decimal digits to "9".
   11246              :      *
   11247              :      * Without loss of generality, we can ignore the weight of rlen2 and treat
   11248              :      * it as a pure integer for the purposes of this discussion.  The process
   11249              :      * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
   11250              :      * is a 64-bit integer formed from the first 4 NBASE digits copied from
   11251              :      * rlen.  Since this trivially factors into smaller pieces that fit in
   11252              :      * 64-bit integers, the task of choosing a random value uniformly from the
   11253              :      * rlen2 + 1 possible values in [0, rlen2] is much simpler.
   11254              :      *
   11255              :      * If the random value selected is too large, it is rejected, and we try
   11256              :      * again until we get a result <= rlen, ensuring that the overall result
   11257              :      * is uniform (no particular value is any more likely than any other).
   11258              :      *
   11259              :      * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
   11260              :      * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
   11261              :      * when DEC_DIGITS is 4). Therefore the probability of needing to reject
   11262              :      * the value chosen and retry is less than 1e-13.
   11263              :      */
   11264        16710 :     rlen64 = (uint64) rlen.digits[0];
   11265        16710 :     rlen64_ndigits = 1;
   11266        38106 :     while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
   11267              :     {
   11268        21396 :         rlen64 *= NBASE;
   11269        21396 :         if (rlen64_ndigits < rlen.ndigits)
   11270         3306 :             rlen64 += rlen.digits[rlen64_ndigits];
   11271        21396 :         rlen64_ndigits++;
   11272              :     }
   11273              : 
   11274              :     /* Loop until we get a result <= rlen */
   11275              :     do
   11276              :     {
   11277              :         NumericDigit *res_digits;
   11278              :         uint64      rand;
   11279              :         int         whole_ndigits;
   11280              : 
   11281        16710 :         alloc_var(result, res_ndigits);
   11282        16710 :         result->sign = NUMERIC_POS;
   11283        16710 :         result->weight = rlen.weight;
   11284        16710 :         result->dscale = rscale;
   11285        16710 :         res_digits = result->digits;
   11286              : 
   11287              :         /*
   11288              :          * Set the first rlen64_ndigits using a random value in [0, rlen64].
   11289              :          *
   11290              :          * If this is the whole result, and rscale is not a multiple of
   11291              :          * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
   11292              :          * multiple of pow10.
   11293              :          */
   11294        16710 :         if (rlen64_ndigits == res_ndigits && pow10 != 1)
   11295        10566 :             rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
   11296              :         else
   11297         6144 :             rand = pg_prng_uint64_range(state, 0, rlen64);
   11298              : 
   11299        54816 :         for (i = rlen64_ndigits - 1; i >= 0; i--)
   11300              :         {
   11301        38106 :             res_digits[i] = (NumericDigit) (rand % NBASE);
   11302        38106 :             rand = rand / NBASE;
   11303              :         }
   11304              : 
   11305              :         /*
   11306              :          * Set the remaining digits to random values in range [0, NBASE),
   11307              :          * noting that the last digit needs to be a multiple of pow10.
   11308              :          */
   11309        16710 :         whole_ndigits = res_ndigits;
   11310        16710 :         if (pow10 != 1)
   11311        16605 :             whole_ndigits--;
   11312              : 
   11313              :         /* Set whole digits in groups of 4 for best performance */
   11314        16710 :         i = rlen64_ndigits;
   11315        16740 :         while (i < whole_ndigits - 3)
   11316              :         {
   11317           30 :             rand = pg_prng_uint64_range(state, 0,
   11318              :                                         (uint64) NBASE * NBASE * NBASE * NBASE - 1);
   11319           30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
   11320           30 :             rand = rand / NBASE;
   11321           30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
   11322           30 :             rand = rand / NBASE;
   11323           30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
   11324           30 :             rand = rand / NBASE;
   11325           30 :             res_digits[i++] = (NumericDigit) rand;
   11326              :         }
   11327              : 
   11328              :         /* Remaining whole digits */
   11329        16815 :         while (i < whole_ndigits)
   11330              :         {
   11331          105 :             rand = pg_prng_uint64_range(state, 0, NBASE - 1);
   11332          105 :             res_digits[i++] = (NumericDigit) rand;
   11333              :         }
   11334              : 
   11335              :         /* Final partial digit (multiple of pow10) */
   11336        16710 :         if (i < res_ndigits)
   11337              :         {
   11338         6039 :             rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
   11339         6039 :             res_digits[i] = (NumericDigit) rand;
   11340              :         }
   11341              : 
   11342              :         /* Remove leading/trailing zeroes */
   11343        16710 :         strip_var(result);
   11344              : 
   11345              :         /* If result > rlen, try again */
   11346              : 
   11347        16710 :     } while (cmp_var(result, &rlen) > 0);
   11348              : 
   11349              :     /* Offset the result to the required range */
   11350        16710 :     add_var(result, rmin, result);
   11351              : 
   11352        16710 :     free_var(&rlen);
   11353              : }
   11354              : 
   11355              : 
   11356              : /* ----------------------------------------------------------------------
   11357              :  *
   11358              :  * Following are the lowest level functions that operate unsigned
   11359              :  * on the variable level
   11360              :  *
   11361              :  * ----------------------------------------------------------------------
   11362              :  */
   11363              : 
   11364              : 
   11365              : /* ----------
   11366              :  * cmp_abs() -
   11367              :  *
   11368              :  *  Compare the absolute values of var1 and var2
   11369              :  *  Returns:    -1 for ABS(var1) < ABS(var2)
   11370              :  *              0  for ABS(var1) == ABS(var2)
   11371              :  *              1  for ABS(var1) > ABS(var2)
   11372              :  * ----------
   11373              :  */
   11374              : static int
   11375       354786 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
   11376              : {
   11377       709572 :     return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
   11378       354786 :                           var2->digits, var2->ndigits, var2->weight);
   11379              : }
   11380              : 
   11381              : /* ----------
   11382              :  * cmp_abs_common() -
   11383              :  *
   11384              :  *  Main routine of cmp_abs(). This function can be used by both
   11385              :  *  NumericVar and Numeric.
   11386              :  * ----------
   11387              :  */
   11388              : static int
   11389     13855202 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
   11390              :                const NumericDigit *var2digits, int var2ndigits, int var2weight)
   11391              : {
   11392     13855202 :     int         i1 = 0;
   11393     13855202 :     int         i2 = 0;
   11394              : 
   11395              :     /* Check any digits before the first common digit */
   11396              : 
   11397     13855202 :     while (var1weight > var2weight && i1 < var1ndigits)
   11398              :     {
   11399        13135 :         if (var1digits[i1++] != 0)
   11400        13135 :             return 1;
   11401            0 :         var1weight--;
   11402              :     }
   11403     13842067 :     while (var2weight > var1weight && i2 < var2ndigits)
   11404              :     {
   11405        75337 :         if (var2digits[i2++] != 0)
   11406        75337 :             return -1;
   11407            0 :         var2weight--;
   11408              :     }
   11409              : 
   11410              :     /* At this point, either w1 == w2 or we've run out of digits */
   11411              : 
   11412     13766730 :     if (var1weight == var2weight)
   11413              :     {
   11414     21660579 :         while (i1 < var1ndigits && i2 < var2ndigits)
   11415              :         {
   11416     14549311 :             int         stat = var1digits[i1++] - var2digits[i2++];
   11417              : 
   11418     14549311 :             if (stat)
   11419              :             {
   11420      6652267 :                 if (stat > 0)
   11421      3940830 :                     return 1;
   11422      2711437 :                 return -1;
   11423              :             }
   11424              :         }
   11425              :     }
   11426              : 
   11427              :     /*
   11428              :      * At this point, we've run out of digits on one side or the other; so any
   11429              :      * remaining nonzero digits imply that side is larger
   11430              :      */
   11431      7114631 :     while (i1 < var1ndigits)
   11432              :     {
   11433         4770 :         if (var1digits[i1++] != 0)
   11434         4602 :             return 1;
   11435              :     }
   11436      7110023 :     while (i2 < var2ndigits)
   11437              :     {
   11438          630 :         if (var2digits[i2++] != 0)
   11439          468 :             return -1;
   11440              :     }
   11441              : 
   11442      7109393 :     return 0;
   11443              : }
   11444              : 
   11445              : 
   11446              : /*
   11447              :  * add_abs() -
   11448              :  *
   11449              :  *  Add the absolute values of two variables into result.
   11450              :  *  result might point to one of the operands without danger.
   11451              :  */
   11452              : static void
   11453       223354 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
   11454              : {
   11455              :     NumericDigit *res_buf;
   11456              :     NumericDigit *res_digits;
   11457              :     int         res_ndigits;
   11458              :     int         res_weight;
   11459              :     int         res_rscale,
   11460              :                 rscale1,
   11461              :                 rscale2;
   11462              :     int         res_dscale;
   11463              :     int         i,
   11464              :                 i1,
   11465              :                 i2;
   11466       223354 :     int         carry = 0;
   11467              : 
   11468              :     /* copy these values into local vars for speed in inner loop */
   11469       223354 :     int         var1ndigits = var1->ndigits;
   11470       223354 :     int         var2ndigits = var2->ndigits;
   11471       223354 :     NumericDigit *var1digits = var1->digits;
   11472       223354 :     NumericDigit *var2digits = var2->digits;
   11473              : 
   11474       223354 :     res_weight = Max(var1->weight, var2->weight) + 1;
   11475              : 
   11476       223354 :     res_dscale = Max(var1->dscale, var2->dscale);
   11477              : 
   11478              :     /* Note: here we are figuring rscale in base-NBASE digits */
   11479       223354 :     rscale1 = var1->ndigits - var1->weight - 1;
   11480       223354 :     rscale2 = var2->ndigits - var2->weight - 1;
   11481       223354 :     res_rscale = Max(rscale1, rscale2);
   11482              : 
   11483       223354 :     res_ndigits = res_rscale + res_weight + 1;
   11484       223354 :     if (res_ndigits <= 0)
   11485            0 :         res_ndigits = 1;
   11486              : 
   11487       223354 :     res_buf = digitbuf_alloc(res_ndigits + 1);
   11488       223354 :     res_buf[0] = 0;             /* spare digit for later rounding */
   11489       223354 :     res_digits = res_buf + 1;
   11490              : 
   11491       223354 :     i1 = res_rscale + var1->weight + 1;
   11492       223354 :     i2 = res_rscale + var2->weight + 1;
   11493      1820567 :     for (i = res_ndigits - 1; i >= 0; i--)
   11494              :     {
   11495      1597213 :         i1--;
   11496      1597213 :         i2--;
   11497      1597213 :         if (i1 >= 0 && i1 < var1ndigits)
   11498       708639 :             carry += var1digits[i1];
   11499      1597213 :         if (i2 >= 0 && i2 < var2ndigits)
   11500       568491 :             carry += var2digits[i2];
   11501              : 
   11502      1597213 :         if (carry >= NBASE)
   11503              :         {
   11504       113008 :             res_digits[i] = carry - NBASE;
   11505       113008 :             carry = 1;
   11506              :         }
   11507              :         else
   11508              :         {
   11509      1484205 :             res_digits[i] = carry;
   11510      1484205 :             carry = 0;
   11511              :         }
   11512              :     }
   11513              : 
   11514              :     Assert(carry == 0);         /* else we failed to allow for carry out */
   11515              : 
   11516       223354 :     digitbuf_free(result->buf);
   11517       223354 :     result->ndigits = res_ndigits;
   11518       223354 :     result->buf = res_buf;
   11519       223354 :     result->digits = res_digits;
   11520       223354 :     result->weight = res_weight;
   11521       223354 :     result->dscale = res_dscale;
   11522              : 
   11523              :     /* Remove leading/trailing zeroes */
   11524       223354 :     strip_var(result);
   11525       223354 : }
   11526              : 
   11527              : 
   11528              : /*
   11529              :  * sub_abs()
   11530              :  *
   11531              :  *  Subtract the absolute value of var2 from the absolute value of var1
   11532              :  *  and store in result. result might point to one of the operands
   11533              :  *  without danger.
   11534              :  *
   11535              :  *  ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
   11536              :  */
   11537              : static void
   11538       327697 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
   11539              : {
   11540              :     NumericDigit *res_buf;
   11541              :     NumericDigit *res_digits;
   11542              :     int         res_ndigits;
   11543              :     int         res_weight;
   11544              :     int         res_rscale,
   11545              :                 rscale1,
   11546              :                 rscale2;
   11547              :     int         res_dscale;
   11548              :     int         i,
   11549              :                 i1,
   11550              :                 i2;
   11551       327697 :     int         borrow = 0;
   11552              : 
   11553              :     /* copy these values into local vars for speed in inner loop */
   11554       327697 :     int         var1ndigits = var1->ndigits;
   11555       327697 :     int         var2ndigits = var2->ndigits;
   11556       327697 :     NumericDigit *var1digits = var1->digits;
   11557       327697 :     NumericDigit *var2digits = var2->digits;
   11558              : 
   11559       327697 :     res_weight = var1->weight;
   11560              : 
   11561       327697 :     res_dscale = Max(var1->dscale, var2->dscale);
   11562              : 
   11563              :     /* Note: here we are figuring rscale in base-NBASE digits */
   11564       327697 :     rscale1 = var1->ndigits - var1->weight - 1;
   11565       327697 :     rscale2 = var2->ndigits - var2->weight - 1;
   11566       327697 :     res_rscale = Max(rscale1, rscale2);
   11567              : 
   11568       327697 :     res_ndigits = res_rscale + res_weight + 1;
   11569       327697 :     if (res_ndigits <= 0)
   11570            0 :         res_ndigits = 1;
   11571              : 
   11572       327697 :     res_buf = digitbuf_alloc(res_ndigits + 1);
   11573       327697 :     res_buf[0] = 0;             /* spare digit for later rounding */
   11574       327697 :     res_digits = res_buf + 1;
   11575              : 
   11576       327697 :     i1 = res_rscale + var1->weight + 1;
   11577       327697 :     i2 = res_rscale + var2->weight + 1;
   11578      2594403 :     for (i = res_ndigits - 1; i >= 0; i--)
   11579              :     {
   11580      2266706 :         i1--;
   11581      2266706 :         i2--;
   11582      2266706 :         if (i1 >= 0 && i1 < var1ndigits)
   11583      2056135 :             borrow += var1digits[i1];
   11584      2266706 :         if (i2 >= 0 && i2 < var2ndigits)
   11585      2016061 :             borrow -= var2digits[i2];
   11586              : 
   11587      2266706 :         if (borrow < 0)
   11588              :         {
   11589       227156 :             res_digits[i] = borrow + NBASE;
   11590       227156 :             borrow = -1;
   11591              :         }
   11592              :         else
   11593              :         {
   11594      2039550 :             res_digits[i] = borrow;
   11595      2039550 :             borrow = 0;
   11596              :         }
   11597              :     }
   11598              : 
   11599              :     Assert(borrow == 0);        /* else caller gave us var1 < var2 */
   11600              : 
   11601       327697 :     digitbuf_free(result->buf);
   11602       327697 :     result->ndigits = res_ndigits;
   11603       327697 :     result->buf = res_buf;
   11604       327697 :     result->digits = res_digits;
   11605       327697 :     result->weight = res_weight;
   11606       327697 :     result->dscale = res_dscale;
   11607              : 
   11608              :     /* Remove leading/trailing zeroes */
   11609       327697 :     strip_var(result);
   11610       327697 : }
   11611              : 
   11612              : /*
   11613              :  * round_var
   11614              :  *
   11615              :  * Round the value of a variable to no more than rscale decimal digits
   11616              :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
   11617              :  * rounding before the decimal point.
   11618              :  */
   11619              : static void
   11620       124439 : round_var(NumericVar *var, int rscale)
   11621              : {
   11622       124439 :     NumericDigit *digits = var->digits;
   11623              :     int         di;
   11624              :     int         ndigits;
   11625              :     int         carry;
   11626              : 
   11627       124439 :     var->dscale = rscale;
   11628              : 
   11629              :     /* decimal digits wanted */
   11630       124439 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
   11631              : 
   11632              :     /*
   11633              :      * If di = 0, the value loses all digits, but could round up to 1 if its
   11634              :      * first extra digit is >= 5.  If di < 0 the result must be 0.
   11635              :      */
   11636       124439 :     if (di < 0)
   11637              :     {
   11638           52 :         var->ndigits = 0;
   11639           52 :         var->weight = 0;
   11640           52 :         var->sign = NUMERIC_POS;
   11641              :     }
   11642              :     else
   11643              :     {
   11644              :         /* NBASE digits wanted */
   11645       124387 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
   11646              : 
   11647              :         /* 0, or number of decimal digits to keep in last NBASE digit */
   11648       124387 :         di %= DEC_DIGITS;
   11649              : 
   11650       124387 :         if (ndigits < var->ndigits ||
   11651        22961 :             (ndigits == var->ndigits && di > 0))
   11652              :         {
   11653       103153 :             var->ndigits = ndigits;
   11654              : 
   11655              : #if DEC_DIGITS == 1
   11656              :             /* di must be zero */
   11657              :             carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
   11658              : #else
   11659       103153 :             if (di == 0)
   11660        82215 :                 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
   11661              :             else
   11662              :             {
   11663              :                 /* Must round within last NBASE digit */
   11664              :                 int         extra,
   11665              :                             pow10;
   11666              : 
   11667              : #if DEC_DIGITS == 4
   11668        20938 :                 pow10 = round_powers[di];
   11669              : #elif DEC_DIGITS == 2
   11670              :                 pow10 = 10;
   11671              : #else
   11672              : #error unsupported NBASE
   11673              : #endif
   11674        20938 :                 extra = digits[--ndigits] % pow10;
   11675        20938 :                 digits[ndigits] -= extra;
   11676        20938 :                 carry = 0;
   11677        20938 :                 if (extra >= pow10 / 2)
   11678              :                 {
   11679         9725 :                     pow10 += digits[ndigits];
   11680         9725 :                     if (pow10 >= NBASE)
   11681              :                     {
   11682          406 :                         pow10 -= NBASE;
   11683          406 :                         carry = 1;
   11684              :                     }
   11685         9725 :                     digits[ndigits] = pow10;
   11686              :                 }
   11687              :             }
   11688              : #endif
   11689              : 
   11690              :             /* Propagate carry if needed */
   11691       120018 :             while (carry)
   11692              :             {
   11693        16865 :                 carry += digits[--ndigits];
   11694        16865 :                 if (carry >= NBASE)
   11695              :                 {
   11696        12313 :                     digits[ndigits] = carry - NBASE;
   11697        12313 :                     carry = 1;
   11698              :                 }
   11699              :                 else
   11700              :                 {
   11701         4552 :                     digits[ndigits] = carry;
   11702         4552 :                     carry = 0;
   11703              :                 }
   11704              :             }
   11705              : 
   11706       103153 :             if (ndigits < 0)
   11707              :             {
   11708              :                 Assert(ndigits == -1);  /* better not have added > 1 digit */
   11709              :                 Assert(var->digits > var->buf);
   11710           48 :                 var->digits--;
   11711           48 :                 var->ndigits++;
   11712           48 :                 var->weight++;
   11713              :             }
   11714              :         }
   11715              :     }
   11716       124439 : }
   11717              : 
   11718              : /*
   11719              :  * trunc_var
   11720              :  *
   11721              :  * Truncate (towards zero) the value of a variable at rscale decimal digits
   11722              :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
   11723              :  * truncation before the decimal point.
   11724              :  */
   11725              : static void
   11726       210462 : trunc_var(NumericVar *var, int rscale)
   11727              : {
   11728              :     int         di;
   11729              :     int         ndigits;
   11730              : 
   11731       210462 :     var->dscale = rscale;
   11732              : 
   11733              :     /* decimal digits wanted */
   11734       210462 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
   11735              : 
   11736              :     /*
   11737              :      * If di <= 0, the value loses all digits.
   11738              :      */
   11739       210462 :     if (di <= 0)
   11740              :     {
   11741           45 :         var->ndigits = 0;
   11742           45 :         var->weight = 0;
   11743           45 :         var->sign = NUMERIC_POS;
   11744              :     }
   11745              :     else
   11746              :     {
   11747              :         /* NBASE digits wanted */
   11748       210417 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
   11749              : 
   11750       210417 :         if (ndigits <= var->ndigits)
   11751              :         {
   11752       210282 :             var->ndigits = ndigits;
   11753              : 
   11754              : #if DEC_DIGITS == 1
   11755              :             /* no within-digit stuff to worry about */
   11756              : #else
   11757              :             /* 0, or number of decimal digits to keep in last NBASE digit */
   11758       210282 :             di %= DEC_DIGITS;
   11759              : 
   11760       210282 :             if (di > 0)
   11761              :             {
   11762              :                 /* Must truncate within last NBASE digit */
   11763           53 :                 NumericDigit *digits = var->digits;
   11764              :                 int         extra,
   11765              :                             pow10;
   11766              : 
   11767              : #if DEC_DIGITS == 4
   11768           53 :                 pow10 = round_powers[di];
   11769              : #elif DEC_DIGITS == 2
   11770              :                 pow10 = 10;
   11771              : #else
   11772              : #error unsupported NBASE
   11773              : #endif
   11774           53 :                 extra = digits[--ndigits] % pow10;
   11775           53 :                 digits[ndigits] -= extra;
   11776              :             }
   11777              : #endif
   11778              :         }
   11779              :     }
   11780       210462 : }
   11781              : 
   11782              : /*
   11783              :  * strip_var
   11784              :  *
   11785              :  * Strip any leading and trailing zeroes from a numeric variable
   11786              :  */
   11787              : static void
   11788      1644593 : strip_var(NumericVar *var)
   11789              : {
   11790      1644593 :     NumericDigit *digits = var->digits;
   11791      1644593 :     int         ndigits = var->ndigits;
   11792              : 
   11793              :     /* Strip leading zeroes */
   11794      2818726 :     while (ndigits > 0 && *digits == 0)
   11795              :     {
   11796      1174133 :         digits++;
   11797      1174133 :         var->weight--;
   11798      1174133 :         ndigits--;
   11799              :     }
   11800              : 
   11801              :     /* Strip trailing zeroes */
   11802      1982341 :     while (ndigits > 0 && digits[ndigits - 1] == 0)
   11803       337748 :         ndigits--;
   11804              : 
   11805              :     /* If it's zero, normalize the sign and weight */
   11806      1644593 :     if (ndigits == 0)
   11807              :     {
   11808        25772 :         var->sign = NUMERIC_POS;
   11809        25772 :         var->weight = 0;
   11810              :     }
   11811              : 
   11812      1644593 :     var->digits = digits;
   11813      1644593 :     var->ndigits = ndigits;
   11814      1644593 : }
   11815              : 
   11816              : 
   11817              : /* ----------------------------------------------------------------------
   11818              :  *
   11819              :  * Fast sum accumulator functions
   11820              :  *
   11821              :  * ----------------------------------------------------------------------
   11822              :  */
   11823              : 
   11824              : /*
   11825              :  * Reset the accumulator's value to zero.  The buffers to hold the digits
   11826              :  * are not free'd.
   11827              :  */
   11828              : static void
   11829            9 : accum_sum_reset(NumericSumAccum *accum)
   11830              : {
   11831              :     int         i;
   11832              : 
   11833            9 :     accum->dscale = 0;
   11834           33 :     for (i = 0; i < accum->ndigits; i++)
   11835              :     {
   11836           24 :         accum->pos_digits[i] = 0;
   11837           24 :         accum->neg_digits[i] = 0;
   11838              :     }
   11839            9 : }
   11840              : 
   11841              : /*
   11842              :  * Accumulate a new value.
   11843              :  */
   11844              : static void
   11845      1177846 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
   11846              : {
   11847              :     int32      *accum_digits;
   11848              :     int         i,
   11849              :                 val_i;
   11850              :     int         val_ndigits;
   11851              :     NumericDigit *val_digits;
   11852              : 
   11853              :     /*
   11854              :      * If we have accumulated too many values since the last carry
   11855              :      * propagation, do it now, to avoid overflowing.  (We could allow more
   11856              :      * than NBASE - 1, if we reserved two extra digits, rather than one, for
   11857              :      * carry propagation.  But even with NBASE - 1, this needs to be done so
   11858              :      * seldom, that the performance difference is negligible.)
   11859              :      */
   11860      1177846 :     if (accum->num_uncarried == NBASE - 1)
   11861           81 :         accum_sum_carry(accum);
   11862              : 
   11863              :     /*
   11864              :      * Adjust the weight or scale of the old value, so that it can accommodate
   11865              :      * the new value.
   11866              :      */
   11867      1177846 :     accum_sum_rescale(accum, val);
   11868              : 
   11869              :     /* */
   11870      1177846 :     if (val->sign == NUMERIC_POS)
   11871       877507 :         accum_digits = accum->pos_digits;
   11872              :     else
   11873       300339 :         accum_digits = accum->neg_digits;
   11874              : 
   11875              :     /* copy these values into local vars for speed in loop */
   11876      1177846 :     val_ndigits = val->ndigits;
   11877      1177846 :     val_digits = val->digits;
   11878              : 
   11879      1177846 :     i = accum->weight - val->weight;
   11880      5944949 :     for (val_i = 0; val_i < val_ndigits; val_i++)
   11881              :     {
   11882      4767103 :         accum_digits[i] += (int32) val_digits[val_i];
   11883      4767103 :         i++;
   11884              :     }
   11885              : 
   11886      1177846 :     accum->num_uncarried++;
   11887      1177846 : }
   11888              : 
   11889              : /*
   11890              :  * Propagate carries.
   11891              :  */
   11892              : static void
   11893        86376 : accum_sum_carry(NumericSumAccum *accum)
   11894              : {
   11895              :     int         i;
   11896              :     int         ndigits;
   11897              :     int32      *dig;
   11898              :     int32       carry;
   11899        86376 :     int32       newdig = 0;
   11900              : 
   11901              :     /*
   11902              :      * If no new values have been added since last carry propagation, nothing
   11903              :      * to do.
   11904              :      */
   11905        86376 :     if (accum->num_uncarried == 0)
   11906           36 :         return;
   11907              : 
   11908              :     /*
   11909              :      * We maintain that the weight of the accumulator is always one larger
   11910              :      * than needed to hold the current value, before carrying, to make sure
   11911              :      * there is enough space for the possible extra digit when carry is
   11912              :      * propagated.  We cannot expand the buffer here, unless we require
   11913              :      * callers of accum_sum_final() to switch to the right memory context.
   11914              :      */
   11915              :     Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
   11916              : 
   11917        86340 :     ndigits = accum->ndigits;
   11918              : 
   11919              :     /* Propagate carry in the positive sum */
   11920        86340 :     dig = accum->pos_digits;
   11921        86340 :     carry = 0;
   11922      1302754 :     for (i = ndigits - 1; i >= 0; i--)
   11923              :     {
   11924      1216414 :         newdig = dig[i] + carry;
   11925      1216414 :         if (newdig >= NBASE)
   11926              :         {
   11927        55403 :             carry = newdig / NBASE;
   11928        55403 :             newdig -= carry * NBASE;
   11929              :         }
   11930              :         else
   11931      1161011 :             carry = 0;
   11932      1216414 :         dig[i] = newdig;
   11933              :     }
   11934              :     /* Did we use up the digit reserved for carry propagation? */
   11935        86340 :     if (newdig > 0)
   11936         1316 :         accum->have_carry_space = false;
   11937              : 
   11938              :     /* And the same for the negative sum */
   11939        86340 :     dig = accum->neg_digits;
   11940        86340 :     carry = 0;
   11941      1302754 :     for (i = ndigits - 1; i >= 0; i--)
   11942              :     {
   11943      1216414 :         newdig = dig[i] + carry;
   11944      1216414 :         if (newdig >= NBASE)
   11945              :         {
   11946           99 :             carry = newdig / NBASE;
   11947           99 :             newdig -= carry * NBASE;
   11948              :         }
   11949              :         else
   11950      1216315 :             carry = 0;
   11951      1216414 :         dig[i] = newdig;
   11952              :     }
   11953        86340 :     if (newdig > 0)
   11954           15 :         accum->have_carry_space = false;
   11955              : 
   11956        86340 :     accum->num_uncarried = 0;
   11957              : }
   11958              : 
   11959              : /*
   11960              :  * Re-scale accumulator to accommodate new value.
   11961              :  *
   11962              :  * If the new value has more digits than the current digit buffers in the
   11963              :  * accumulator, enlarge the buffers.
   11964              :  */
   11965              : static void
   11966      1177846 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
   11967              : {
   11968      1177846 :     int         old_weight = accum->weight;
   11969      1177846 :     int         old_ndigits = accum->ndigits;
   11970              :     int         accum_ndigits;
   11971              :     int         accum_weight;
   11972              :     int         accum_rscale;
   11973              :     int         val_rscale;
   11974              : 
   11975      1177846 :     accum_weight = old_weight;
   11976      1177846 :     accum_ndigits = old_ndigits;
   11977              : 
   11978              :     /*
   11979              :      * Does the new value have a larger weight? If so, enlarge the buffers,
   11980              :      * and shift the existing value to the new weight, by adding leading
   11981              :      * zeros.
   11982              :      *
   11983              :      * We enforce that the accumulator always has a weight one larger than
   11984              :      * needed for the inputs, so that we have space for an extra digit at the
   11985              :      * final carry-propagation phase, if necessary.
   11986              :      */
   11987      1177846 :     if (val->weight >= accum_weight)
   11988              :     {
   11989       131106 :         accum_weight = val->weight + 1;
   11990       131106 :         accum_ndigits = accum_ndigits + (accum_weight - old_weight);
   11991              :     }
   11992              : 
   11993              :     /*
   11994              :      * Even though the new value is small, we might've used up the space
   11995              :      * reserved for the carry digit in the last call to accum_sum_carry().  If
   11996              :      * so, enlarge to make room for another one.
   11997              :      */
   11998      1046740 :     else if (!accum->have_carry_space)
   11999              :     {
   12000           42 :         accum_weight++;
   12001           42 :         accum_ndigits++;
   12002              :     }
   12003              : 
   12004              :     /* Is the new value wider on the right side? */
   12005      1177846 :     accum_rscale = accum_ndigits - accum_weight - 1;
   12006      1177846 :     val_rscale = val->ndigits - val->weight - 1;
   12007      1177846 :     if (val_rscale > accum_rscale)
   12008        86117 :         accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
   12009              : 
   12010      1177846 :     if (accum_ndigits != old_ndigits ||
   12011              :         accum_weight != old_weight)
   12012              :     {
   12013              :         int32      *new_pos_digits;
   12014              :         int32      *new_neg_digits;
   12015              :         int         weightdiff;
   12016              : 
   12017       131301 :         weightdiff = accum_weight - old_weight;
   12018              : 
   12019       131301 :         new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
   12020       131301 :         new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
   12021              : 
   12022       131301 :         if (accum->pos_digits)
   12023              :         {
   12024        45219 :             memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
   12025              :                    old_ndigits * sizeof(int32));
   12026        45219 :             pfree(accum->pos_digits);
   12027              : 
   12028        45219 :             memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
   12029              :                    old_ndigits * sizeof(int32));
   12030        45219 :             pfree(accum->neg_digits);
   12031              :         }
   12032              : 
   12033       131301 :         accum->pos_digits = new_pos_digits;
   12034       131301 :         accum->neg_digits = new_neg_digits;
   12035              : 
   12036       131301 :         accum->weight = accum_weight;
   12037       131301 :         accum->ndigits = accum_ndigits;
   12038              : 
   12039              :         Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
   12040       131301 :         accum->have_carry_space = true;
   12041              :     }
   12042              : 
   12043      1177846 :     if (val->dscale > accum->dscale)
   12044          150 :         accum->dscale = val->dscale;
   12045      1177846 : }
   12046              : 
   12047              : /*
   12048              :  * Return the current value of the accumulator.  This perform final carry
   12049              :  * propagation, and adds together the positive and negative sums.
   12050              :  *
   12051              :  * Unlike all the other routines, the caller is not required to switch to
   12052              :  * the memory context that holds the accumulator.
   12053              :  */
   12054              : static void
   12055        86295 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
   12056              : {
   12057              :     int         i;
   12058              :     NumericVar  pos_var;
   12059              :     NumericVar  neg_var;
   12060              : 
   12061        86295 :     if (accum->ndigits == 0)
   12062              :     {
   12063            0 :         set_var_from_var(&const_zero, result);
   12064            0 :         return;
   12065              :     }
   12066              : 
   12067              :     /* Perform final carry */
   12068        86295 :     accum_sum_carry(accum);
   12069              : 
   12070              :     /* Create NumericVars representing the positive and negative sums */
   12071        86295 :     init_var(&pos_var);
   12072        86295 :     init_var(&neg_var);
   12073              : 
   12074        86295 :     pos_var.ndigits = neg_var.ndigits = accum->ndigits;
   12075        86295 :     pos_var.weight = neg_var.weight = accum->weight;
   12076        86295 :     pos_var.dscale = neg_var.dscale = accum->dscale;
   12077        86295 :     pos_var.sign = NUMERIC_POS;
   12078        86295 :     neg_var.sign = NUMERIC_NEG;
   12079              : 
   12080        86295 :     pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
   12081        86295 :     neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
   12082              : 
   12083      1302525 :     for (i = 0; i < accum->ndigits; i++)
   12084              :     {
   12085              :         Assert(accum->pos_digits[i] < NBASE);
   12086      1216230 :         pos_var.digits[i] = (int16) accum->pos_digits[i];
   12087              : 
   12088              :         Assert(accum->neg_digits[i] < NBASE);
   12089      1216230 :         neg_var.digits[i] = (int16) accum->neg_digits[i];
   12090              :     }
   12091              : 
   12092              :     /* And add them together */
   12093        86295 :     add_var(&pos_var, &neg_var, result);
   12094              : 
   12095              :     /* Remove leading/trailing zeroes */
   12096        86295 :     strip_var(result);
   12097              : }
   12098              : 
   12099              : /*
   12100              :  * Copy an accumulator's state.
   12101              :  *
   12102              :  * 'dst' is assumed to be uninitialized beforehand.  No attempt is made at
   12103              :  * freeing old values.
   12104              :  */
   12105              : static void
   12106           21 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
   12107              : {
   12108           21 :     dst->pos_digits = palloc(src->ndigits * sizeof(int32));
   12109           21 :     dst->neg_digits = palloc(src->ndigits * sizeof(int32));
   12110              : 
   12111           21 :     memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
   12112           21 :     memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
   12113           21 :     dst->num_uncarried = src->num_uncarried;
   12114           21 :     dst->ndigits = src->ndigits;
   12115           21 :     dst->weight = src->weight;
   12116           21 :     dst->dscale = src->dscale;
   12117           21 : }
   12118              : 
   12119              : /*
   12120              :  * Add the current value of 'accum2' into 'accum'.
   12121              :  */
   12122              : static void
   12123           21 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
   12124              : {
   12125              :     NumericVar  tmp_var;
   12126              : 
   12127           21 :     init_var(&tmp_var);
   12128              : 
   12129           21 :     accum_sum_final(accum2, &tmp_var);
   12130           21 :     accum_sum_add(accum, &tmp_var);
   12131              : 
   12132           21 :     free_var(&tmp_var);
   12133           21 : }
        

Generated by: LCOV version 2.0-1