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

Generated by: LCOV version 1.13