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

Generated by: LCOV version 1.11