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