LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - numeric.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC DUB DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 94.1 % 3936 3703 2 231 3 97 3603 4 20
Current Date: 2024-04-14 14:21:10 Functions: 99.5 % 209 208 1 8 200
Baseline: 16@8cea358b128 Branches: 76.4 % 2558 1954 44 560 9 68 1877
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 73 73 73
(60,120] days: 88.2 % 17 15 2 13 2
(120,180] days: 100.0 % 8 8 8
(240..) days: 94.0 % 3838 3607 231 3 3 3601
Function coverage date bins:
[..60] days: 100.0 % 2 2 2
(60,120] days: 100.0 % 2 2 2
(240..) days: 99.5 % 205 204 1 4 200
Branch coverage date bins:
[..60] days: 87.0 % 46 40 6 40
(60,120] days: 71.4 % 14 10 4 10
(120,180] days: 29.2 % 48 14 34 14
(240..) days: 77.1 % 2450 1890 560 9 4 1877

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * numeric.c
                                  4                 :                :  *    An exact numeric data type for the Postgres database system
                                  5                 :                :  *
                                  6                 :                :  * Original coding 1998, Jan Wieck.  Heavily revised 2003, Tom Lane.
                                  7                 :                :  *
                                  8                 :                :  * Many of the algorithmic ideas are borrowed from David M. Smith's "FM"
                                  9                 :                :  * multiple-precision math library, most recently published as Algorithm
                                 10                 :                :  * 786: Multiple-Precision Complex Arithmetic and Functions, ACM
                                 11                 :                :  * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998,
                                 12                 :                :  * pages 359-367.
                                 13                 :                :  *
                                 14                 :                :  * Copyright (c) 1998-2024, PostgreSQL Global Development Group
                                 15                 :                :  *
                                 16                 :                :  * IDENTIFICATION
                                 17                 :                :  *    src/backend/utils/adt/numeric.c
                                 18                 :                :  *
                                 19                 :                :  *-------------------------------------------------------------------------
                                 20                 :                :  */
                                 21                 :                : 
                                 22                 :                : #include "postgres.h"
                                 23                 :                : 
                                 24                 :                : #include <ctype.h>
                                 25                 :                : #include <float.h>
                                 26                 :                : #include <limits.h>
                                 27                 :                : #include <math.h>
                                 28                 :                : 
                                 29                 :                : #include "common/hashfn.h"
                                 30                 :                : #include "common/int.h"
                                 31                 :                : #include "funcapi.h"
                                 32                 :                : #include "lib/hyperloglog.h"
                                 33                 :                : #include "libpq/pqformat.h"
                                 34                 :                : #include "miscadmin.h"
                                 35                 :                : #include "nodes/nodeFuncs.h"
                                 36                 :                : #include "nodes/supportnodes.h"
                                 37                 :                : #include "utils/array.h"
                                 38                 :                : #include "utils/builtins.h"
                                 39                 :                : #include "utils/float.h"
                                 40                 :                : #include "utils/guc.h"
                                 41                 :                : #include "utils/numeric.h"
                                 42                 :                : #include "utils/pg_lsn.h"
                                 43                 :                : #include "utils/sortsupport.h"
                                 44                 :                : 
                                 45                 :                : /* ----------
                                 46                 :                :  * Uncomment the following to enable compilation of dump_numeric()
                                 47                 :                :  * and dump_var() and to get a dump of any result produced by make_result().
                                 48                 :                :  * ----------
                                 49                 :                : #define NUMERIC_DEBUG
                                 50                 :                :  */
                                 51                 :                : 
                                 52                 :                : 
                                 53                 :                : /* ----------
                                 54                 :                :  * Local data types
                                 55                 :                :  *
                                 56                 :                :  * Numeric values are represented in a base-NBASE floating point format.
                                 57                 :                :  * Each "digit" ranges from 0 to NBASE-1.  The type NumericDigit is signed
                                 58                 :                :  * and wide enough to store a digit.  We assume that NBASE*NBASE can fit in
                                 59                 :                :  * an int.  Although the purely calculational routines could handle any even
                                 60                 :                :  * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
                                 61                 :                :  * in NBASE a power of ten, so that I/O conversions and decimal rounding
                                 62                 :                :  * are easy.  Also, it's actually more efficient if NBASE is rather less than
                                 63                 :                :  * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var_fast to
                                 64                 :                :  * postpone processing carries.
                                 65                 :                :  *
                                 66                 :                :  * Values of NBASE other than 10000 are considered of historical interest only
                                 67                 :                :  * and are no longer supported in any sense; no mechanism exists for the client
                                 68                 :                :  * to discover the base, so every client supporting binary mode expects the
                                 69                 :                :  * base-10000 format.  If you plan to change this, also note the numeric
                                 70                 :                :  * abbreviation code, which assumes NBASE=10000.
                                 71                 :                :  * ----------
                                 72                 :                :  */
                                 73                 :                : 
                                 74                 :                : #if 0
                                 75                 :                : #define NBASE       10
                                 76                 :                : #define HALF_NBASE  5
                                 77                 :                : #define DEC_DIGITS  1           /* decimal digits per NBASE digit */
                                 78                 :                : #define MUL_GUARD_DIGITS    4   /* these are measured in NBASE digits */
                                 79                 :                : #define DIV_GUARD_DIGITS    8
                                 80                 :                : 
                                 81                 :                : typedef signed char NumericDigit;
                                 82                 :                : #endif
                                 83                 :                : 
                                 84                 :                : #if 0
                                 85                 :                : #define NBASE       100
                                 86                 :                : #define HALF_NBASE  50
                                 87                 :                : #define DEC_DIGITS  2           /* decimal digits per NBASE digit */
                                 88                 :                : #define MUL_GUARD_DIGITS    3   /* these are measured in NBASE digits */
                                 89                 :                : #define DIV_GUARD_DIGITS    6
                                 90                 :                : 
                                 91                 :                : typedef signed char NumericDigit;
                                 92                 :                : #endif
                                 93                 :                : 
                                 94                 :                : #if 1
                                 95                 :                : #define NBASE       10000
                                 96                 :                : #define HALF_NBASE  5000
                                 97                 :                : #define DEC_DIGITS  4           /* decimal digits per NBASE digit */
                                 98                 :                : #define MUL_GUARD_DIGITS    2   /* these are measured in NBASE digits */
                                 99                 :                : #define DIV_GUARD_DIGITS    4
                                100                 :                : 
                                101                 :                : typedef int16 NumericDigit;
                                102                 :                : #endif
                                103                 :                : 
                                104                 :                : /*
                                105                 :                :  * The Numeric type as stored on disk.
                                106                 :                :  *
                                107                 :                :  * If the high bits of the first word of a NumericChoice (n_header, or
                                108                 :                :  * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
                                109                 :                :  * numeric follows the NumericShort format; if they are NUMERIC_POS or
                                110                 :                :  * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
                                111                 :                :  * the value is a NaN or Infinity.  We currently always store SPECIAL values
                                112                 :                :  * using just two bytes (i.e. only n_header), but previous releases used only
                                113                 :                :  * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
                                114                 :                :  * on disk if a database has been migrated using pg_upgrade.  In either case,
                                115                 :                :  * the low-order bits of a special value's header are reserved and currently
                                116                 :                :  * should always be set to zero.
                                117                 :                :  *
                                118                 :                :  * In the NumericShort format, the remaining 14 bits of the header word
                                119                 :                :  * (n_short.n_header) are allocated as follows: 1 for sign (positive or
                                120                 :                :  * negative), 6 for dynamic scale, and 7 for weight.  In practice, most
                                121                 :                :  * commonly-encountered values can be represented this way.
                                122                 :                :  *
                                123                 :                :  * In the NumericLong format, the remaining 14 bits of the header word
                                124                 :                :  * (n_long.n_sign_dscale) represent the display scale; and the weight is
                                125                 :                :  * stored separately in n_weight.
                                126                 :                :  *
                                127                 :                :  * NOTE: by convention, values in the packed form have been stripped of
                                128                 :                :  * all leading and trailing zero digits (where a "digit" is of base NBASE).
                                129                 :                :  * In particular, if the value is zero, there will be no digits at all!
                                130                 :                :  * The weight is arbitrary in that case, but we normally set it to zero.
                                131                 :                :  */
                                132                 :                : 
                                133                 :                : struct NumericShort
                                134                 :                : {
                                135                 :                :     uint16      n_header;       /* Sign + display scale + weight */
                                136                 :                :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
                                137                 :                : };
                                138                 :                : 
                                139                 :                : struct NumericLong
                                140                 :                : {
                                141                 :                :     uint16      n_sign_dscale;  /* Sign + display scale */
                                142                 :                :     int16       n_weight;       /* Weight of 1st digit  */
                                143                 :                :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
                                144                 :                : };
                                145                 :                : 
                                146                 :                : union NumericChoice
                                147                 :                : {
                                148                 :                :     uint16      n_header;       /* Header word */
                                149                 :                :     struct NumericLong n_long;  /* Long form (4-byte header) */
                                150                 :                :     struct NumericShort n_short;    /* Short form (2-byte header) */
                                151                 :                : };
                                152                 :                : 
                                153                 :                : struct NumericData
                                154                 :                : {
                                155                 :                :     int32       vl_len_;        /* varlena header (do not touch directly!) */
                                156                 :                :     union NumericChoice choice; /* choice of format */
                                157                 :                : };
                                158                 :                : 
                                159                 :                : 
                                160                 :                : /*
                                161                 :                :  * Interpretation of high bits.
                                162                 :                :  */
                                163                 :                : 
                                164                 :                : #define NUMERIC_SIGN_MASK   0xC000
                                165                 :                : #define NUMERIC_POS         0x0000
                                166                 :                : #define NUMERIC_NEG         0x4000
                                167                 :                : #define NUMERIC_SHORT       0x8000
                                168                 :                : #define NUMERIC_SPECIAL     0xC000
                                169                 :                : 
                                170                 :                : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
                                171                 :                : #define NUMERIC_IS_SHORT(n)     (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
                                172                 :                : #define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
                                173                 :                : 
                                174                 :                : #define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
                                175                 :                : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
                                176                 :                : 
                                177                 :                : /*
                                178                 :                :  * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
                                179                 :                :  * header; otherwise, we want the long one.  Instead of testing against each
                                180                 :                :  * value, we can just look at the high bit, for a slight efficiency gain.
                                181                 :                :  */
                                182                 :                : #define NUMERIC_HEADER_IS_SHORT(n)  (((n)->choice.n_header & 0x8000) != 0)
                                183                 :                : #define NUMERIC_HEADER_SIZE(n) \
                                184                 :                :     (VARHDRSZ + sizeof(uint16) + \
                                185                 :                :      (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
                                186                 :                : 
                                187                 :                : /*
                                188                 :                :  * Definitions for special values (NaN, positive infinity, negative infinity).
                                189                 :                :  *
                                190                 :                :  * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
                                191                 :                :  * infinity, 11 for negative infinity.  (This makes the sign bit match where
                                192                 :                :  * it is in a short-format value, though we make no use of that at present.)
                                193                 :                :  * We could mask off the remaining bits before testing the active bits, but
                                194                 :                :  * currently those bits must be zeroes, so masking would just add cycles.
                                195                 :                :  */
                                196                 :                : #define NUMERIC_EXT_SIGN_MASK   0xF000  /* high bits plus NaN/Inf flag bits */
                                197                 :                : #define NUMERIC_NAN             0xC000
                                198                 :                : #define NUMERIC_PINF            0xD000
                                199                 :                : #define NUMERIC_NINF            0xF000
                                200                 :                : #define NUMERIC_INF_SIGN_MASK   0x2000
                                201                 :                : 
                                202                 :                : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
                                203                 :                : #define NUMERIC_IS_NAN(n)       ((n)->choice.n_header == NUMERIC_NAN)
                                204                 :                : #define NUMERIC_IS_PINF(n)      ((n)->choice.n_header == NUMERIC_PINF)
                                205                 :                : #define NUMERIC_IS_NINF(n)      ((n)->choice.n_header == NUMERIC_NINF)
                                206                 :                : #define NUMERIC_IS_INF(n) \
                                207                 :                :     (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
                                208                 :                : 
                                209                 :                : /*
                                210                 :                :  * Short format definitions.
                                211                 :                :  */
                                212                 :                : 
                                213                 :                : #define NUMERIC_SHORT_SIGN_MASK         0x2000
                                214                 :                : #define NUMERIC_SHORT_DSCALE_MASK       0x1F80
                                215                 :                : #define NUMERIC_SHORT_DSCALE_SHIFT      7
                                216                 :                : #define NUMERIC_SHORT_DSCALE_MAX        \
                                217                 :                :     (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
                                218                 :                : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK  0x0040
                                219                 :                : #define NUMERIC_SHORT_WEIGHT_MASK       0x003F
                                220                 :                : #define NUMERIC_SHORT_WEIGHT_MAX        NUMERIC_SHORT_WEIGHT_MASK
                                221                 :                : #define NUMERIC_SHORT_WEIGHT_MIN        (-(NUMERIC_SHORT_WEIGHT_MASK+1))
                                222                 :                : 
                                223                 :                : /*
                                224                 :                :  * Extract sign, display scale, weight.  These macros extract field values
                                225                 :                :  * suitable for the NumericVar format from the Numeric (on-disk) format.
                                226                 :                :  *
                                227                 :                :  * Note that we don't trouble to ensure that dscale and weight read as zero
                                228                 :                :  * for an infinity; however, that doesn't matter since we never convert
                                229                 :                :  * "special" numerics to NumericVar form.  Only the constants defined below
                                230                 :                :  * (const_nan, etc) ever represent a non-finite value as a NumericVar.
                                231                 :                :  */
                                232                 :                : 
                                233                 :                : #define NUMERIC_DSCALE_MASK         0x3FFF
                                234                 :                : #define NUMERIC_DSCALE_MAX          NUMERIC_DSCALE_MASK
                                235                 :                : 
                                236                 :                : #define NUMERIC_SIGN(n) \
                                237                 :                :     (NUMERIC_IS_SHORT(n) ? \
                                238                 :                :         (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
                                239                 :                :          NUMERIC_NEG : NUMERIC_POS) : \
                                240                 :                :         (NUMERIC_IS_SPECIAL(n) ? \
                                241                 :                :          NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
                                242                 :                : #define NUMERIC_DSCALE(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
                                243                 :                :     ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
                                244                 :                :         >> NUMERIC_SHORT_DSCALE_SHIFT \
                                245                 :                :     : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
                                246                 :                : #define NUMERIC_WEIGHT(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
                                247                 :                :     (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
                                248                 :                :         ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
                                249                 :                :      | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
                                250                 :                :     : ((n)->choice.n_long.n_weight))
                                251                 :                : 
                                252                 :                : /* ----------
                                253                 :                :  * NumericVar is the format we use for arithmetic.  The digit-array part
                                254                 :                :  * is the same as the NumericData storage format, but the header is more
                                255                 :                :  * complex.
                                256                 :                :  *
                                257                 :                :  * The value represented by a NumericVar is determined by the sign, weight,
                                258                 :                :  * ndigits, and digits[] array.  If it is a "special" value (NaN or Inf)
                                259                 :                :  * then only the sign field matters; ndigits should be zero, and the weight
                                260                 :                :  * and dscale fields are ignored.
                                261                 :                :  *
                                262                 :                :  * Note: the first digit of a NumericVar's value is assumed to be multiplied
                                263                 :                :  * by NBASE ** weight.  Another way to say it is that there are weight+1
                                264                 :                :  * digits before the decimal point.  It is possible to have weight < 0.
                                265                 :                :  *
                                266                 :                :  * buf points at the physical start of the palloc'd digit buffer for the
                                267                 :                :  * NumericVar.  digits points at the first digit in actual use (the one
                                268                 :                :  * with the specified weight).  We normally leave an unused digit or two
                                269                 :                :  * (preset to zeroes) between buf and digits, so that there is room to store
                                270                 :                :  * a carry out of the top digit without reallocating space.  We just need to
                                271                 :                :  * decrement digits (and increment weight) to make room for the carry digit.
                                272                 :                :  * (There is no such extra space in a numeric value stored in the database,
                                273                 :                :  * only in a NumericVar in memory.)
                                274                 :                :  *
                                275                 :                :  * If buf is NULL then the digit buffer isn't actually palloc'd and should
                                276                 :                :  * not be freed --- see the constants below for an example.
                                277                 :                :  *
                                278                 :                :  * dscale, or display scale, is the nominal precision expressed as number
                                279                 :                :  * of digits after the decimal point (it must always be >= 0 at present).
                                280                 :                :  * dscale may be more than the number of physically stored fractional digits,
                                281                 :                :  * implying that we have suppressed storage of significant trailing zeroes.
                                282                 :                :  * It should never be less than the number of stored digits, since that would
                                283                 :                :  * imply hiding digits that are present.  NOTE that dscale is always expressed
                                284                 :                :  * in *decimal* digits, and so it may correspond to a fractional number of
                                285                 :                :  * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
                                286                 :                :  *
                                287                 :                :  * rscale, or result scale, is the target precision for a computation.
                                288                 :                :  * Like dscale it is expressed as number of *decimal* digits after the decimal
                                289                 :                :  * point, and is always >= 0 at present.
                                290                 :                :  * Note that rscale is not stored in variables --- it's figured on-the-fly
                                291                 :                :  * from the dscales of the inputs.
                                292                 :                :  *
                                293                 :                :  * While we consistently use "weight" to refer to the base-NBASE weight of
                                294                 :                :  * a numeric value, it is convenient in some scale-related calculations to
                                295                 :                :  * make use of the base-10 weight (ie, the approximate log10 of the value).
                                296                 :                :  * To avoid confusion, such a decimal-units weight is called a "dweight".
                                297                 :                :  *
                                298                 :                :  * NB: All the variable-level functions are written in a style that makes it
                                299                 :                :  * possible to give one and the same variable as argument and destination.
                                300                 :                :  * This is feasible because the digit buffer is separate from the variable.
                                301                 :                :  * ----------
                                302                 :                :  */
                                303                 :                : typedef struct NumericVar
                                304                 :                : {
                                305                 :                :     int         ndigits;        /* # of digits in digits[] - can be 0! */
                                306                 :                :     int         weight;         /* weight of first digit */
                                307                 :                :     int         sign;           /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
                                308                 :                :     int         dscale;         /* display scale */
                                309                 :                :     NumericDigit *buf;          /* start of palloc'd space for digits[] */
                                310                 :                :     NumericDigit *digits;       /* base-NBASE digits */
                                311                 :                : } NumericVar;
                                312                 :                : 
                                313                 :                : 
                                314                 :                : /* ----------
                                315                 :                :  * Data for generate_series
                                316                 :                :  * ----------
                                317                 :                :  */
                                318                 :                : typedef struct
                                319                 :                : {
                                320                 :                :     NumericVar  current;
                                321                 :                :     NumericVar  stop;
                                322                 :                :     NumericVar  step;
                                323                 :                : } generate_series_numeric_fctx;
                                324                 :                : 
                                325                 :                : 
                                326                 :                : /* ----------
                                327                 :                :  * Sort support.
                                328                 :                :  * ----------
                                329                 :                :  */
                                330                 :                : typedef struct
                                331                 :                : {
                                332                 :                :     void       *buf;            /* buffer for short varlenas */
                                333                 :                :     int64       input_count;    /* number of non-null values seen */
                                334                 :                :     bool        estimating;     /* true if estimating cardinality */
                                335                 :                : 
                                336                 :                :     hyperLogLogState abbr_card; /* cardinality estimator */
                                337                 :                : } NumericSortSupport;
                                338                 :                : 
                                339                 :                : 
                                340                 :                : /* ----------
                                341                 :                :  * Fast sum accumulator.
                                342                 :                :  *
                                343                 :                :  * NumericSumAccum is used to implement SUM(), and other standard aggregates
                                344                 :                :  * that track the sum of input values.  It uses 32-bit integers to store the
                                345                 :                :  * digits, instead of the normal 16-bit integers (with NBASE=10000).  This
                                346                 :                :  * way, we can safely accumulate up to NBASE - 1 values without propagating
                                347                 :                :  * carry, before risking overflow of any of the digits.  'num_uncarried'
                                348                 :                :  * tracks how many values have been accumulated without propagating carry.
                                349                 :                :  *
                                350                 :                :  * Positive and negative values are accumulated separately, in 'pos_digits'
                                351                 :                :  * and 'neg_digits'.  This is simpler and faster than deciding whether to add
                                352                 :                :  * or subtract from the current value, for each new value (see sub_var() for
                                353                 :                :  * the logic we avoid by doing this).  Both buffers are of same size, and
                                354                 :                :  * have the same weight and scale.  In accum_sum_final(), the positive and
                                355                 :                :  * negative sums are added together to produce the final result.
                                356                 :                :  *
                                357                 :                :  * When a new value has a larger ndigits or weight than the accumulator
                                358                 :                :  * currently does, the accumulator is enlarged to accommodate the new value.
                                359                 :                :  * We normally have one zero digit reserved for carry propagation, and that
                                360                 :                :  * is indicated by the 'have_carry_space' flag.  When accum_sum_carry() uses
                                361                 :                :  * up the reserved digit, it clears the 'have_carry_space' flag.  The next
                                362                 :                :  * call to accum_sum_add() will enlarge the buffer, to make room for the
                                363                 :                :  * extra digit, and set the flag again.
                                364                 :                :  *
                                365                 :                :  * To initialize a new accumulator, simply reset all fields to zeros.
                                366                 :                :  *
                                367                 :                :  * The accumulator does not handle NaNs.
                                368                 :                :  * ----------
                                369                 :                :  */
                                370                 :                : typedef struct NumericSumAccum
                                371                 :                : {
                                372                 :                :     int         ndigits;
                                373                 :                :     int         weight;
                                374                 :                :     int         dscale;
                                375                 :                :     int         num_uncarried;
                                376                 :                :     bool        have_carry_space;
                                377                 :                :     int32      *pos_digits;
                                378                 :                :     int32      *neg_digits;
                                379                 :                : } NumericSumAccum;
                                380                 :                : 
                                381                 :                : 
                                382                 :                : /*
                                383                 :                :  * We define our own macros for packing and unpacking abbreviated-key
                                384                 :                :  * representations for numeric values in order to avoid depending on
                                385                 :                :  * USE_FLOAT8_BYVAL.  The type of abbreviation we use is based only on
                                386                 :                :  * the size of a datum, not the argument-passing convention for float8.
                                387                 :                :  *
                                388                 :                :  * The range of abbreviations for finite values is from +PG_INT64/32_MAX
                                389                 :                :  * to -PG_INT64/32_MAX.  NaN has the abbreviation PG_INT64/32_MIN, and we
                                390                 :                :  * define the sort ordering to make that work out properly (see further
                                391                 :                :  * comments below).  PINF and NINF share the abbreviations of the largest
                                392                 :                :  * and smallest finite abbreviation classes.
                                393                 :                :  */
                                394                 :                : #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
                                395                 :                : #if SIZEOF_DATUM == 8
                                396                 :                : #define NumericAbbrevGetDatum(X) ((Datum) (X))
                                397                 :                : #define DatumGetNumericAbbrev(X) ((int64) (X))
                                398                 :                : #define NUMERIC_ABBREV_NAN       NumericAbbrevGetDatum(PG_INT64_MIN)
                                399                 :                : #define NUMERIC_ABBREV_PINF      NumericAbbrevGetDatum(-PG_INT64_MAX)
                                400                 :                : #define NUMERIC_ABBREV_NINF      NumericAbbrevGetDatum(PG_INT64_MAX)
                                401                 :                : #else
                                402                 :                : #define NumericAbbrevGetDatum(X) ((Datum) (X))
                                403                 :                : #define DatumGetNumericAbbrev(X) ((int32) (X))
                                404                 :                : #define NUMERIC_ABBREV_NAN       NumericAbbrevGetDatum(PG_INT32_MIN)
                                405                 :                : #define NUMERIC_ABBREV_PINF      NumericAbbrevGetDatum(-PG_INT32_MAX)
                                406                 :                : #define NUMERIC_ABBREV_NINF      NumericAbbrevGetDatum(PG_INT32_MAX)
                                407                 :                : #endif
                                408                 :                : 
                                409                 :                : 
                                410                 :                : /* ----------
                                411                 :                :  * Some preinitialized constants
                                412                 :                :  * ----------
                                413                 :                :  */
                                414                 :                : static const NumericDigit const_zero_data[1] = {0};
                                415                 :                : static const NumericVar const_zero =
                                416                 :                : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
                                417                 :                : 
                                418                 :                : static const NumericDigit const_one_data[1] = {1};
                                419                 :                : static const NumericVar const_one =
                                420                 :                : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
                                421                 :                : 
                                422                 :                : static const NumericVar const_minus_one =
                                423                 :                : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
                                424                 :                : 
                                425                 :                : static const NumericDigit const_two_data[1] = {2};
                                426                 :                : static const NumericVar const_two =
                                427                 :                : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
                                428                 :                : 
                                429                 :                : #if DEC_DIGITS == 4
                                430                 :                : static const NumericDigit const_zero_point_nine_data[1] = {9000};
                                431                 :                : #elif DEC_DIGITS == 2
                                432                 :                : static const NumericDigit const_zero_point_nine_data[1] = {90};
                                433                 :                : #elif DEC_DIGITS == 1
                                434                 :                : static const NumericDigit const_zero_point_nine_data[1] = {9};
                                435                 :                : #endif
                                436                 :                : static const NumericVar const_zero_point_nine =
                                437                 :                : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
                                438                 :                : 
                                439                 :                : #if DEC_DIGITS == 4
                                440                 :                : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
                                441                 :                : #elif DEC_DIGITS == 2
                                442                 :                : static const NumericDigit const_one_point_one_data[2] = {1, 10};
                                443                 :                : #elif DEC_DIGITS == 1
                                444                 :                : static const NumericDigit const_one_point_one_data[2] = {1, 1};
                                445                 :                : #endif
                                446                 :                : static const NumericVar const_one_point_one =
                                447                 :                : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
                                448                 :                : 
                                449                 :                : static const NumericVar const_nan =
                                450                 :                : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
                                451                 :                : 
                                452                 :                : static const NumericVar const_pinf =
                                453                 :                : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
                                454                 :                : 
                                455                 :                : static const NumericVar const_ninf =
                                456                 :                : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
                                457                 :                : 
                                458                 :                : #if DEC_DIGITS == 4
                                459                 :                : static const int round_powers[4] = {0, 1000, 100, 10};
                                460                 :                : #endif
                                461                 :                : 
                                462                 :                : 
                                463                 :                : /* ----------
                                464                 :                :  * Local functions
                                465                 :                :  * ----------
                                466                 :                :  */
                                467                 :                : 
                                468                 :                : #ifdef NUMERIC_DEBUG
                                469                 :                : static void dump_numeric(const char *str, Numeric num);
                                470                 :                : static void dump_var(const char *str, NumericVar *var);
                                471                 :                : #else
                                472                 :                : #define dump_numeric(s,n)
                                473                 :                : #define dump_var(s,v)
                                474                 :                : #endif
                                475                 :                : 
                                476                 :                : #define digitbuf_alloc(ndigits)  \
                                477                 :                :     ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
                                478                 :                : #define digitbuf_free(buf)  \
                                479                 :                :     do { \
                                480                 :                :          if ((buf) != NULL) \
                                481                 :                :              pfree(buf); \
                                482                 :                :     } while (0)
                                483                 :                : 
                                484                 :                : #define init_var(v)     memset(v, 0, sizeof(NumericVar))
                                485                 :                : 
                                486                 :                : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
                                487                 :                :     (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
                                488                 :                : #define NUMERIC_NDIGITS(num) \
                                489                 :                :     ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
                                490                 :                : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
                                491                 :                :     ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
                                492                 :                :     (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
                                493                 :                :     (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
                                494                 :                : 
                                495                 :                : static void alloc_var(NumericVar *var, int ndigits);
                                496                 :                : static void free_var(NumericVar *var);
                                497                 :                : static void zero_var(NumericVar *var);
                                498                 :                : 
                                499                 :                : static bool set_var_from_str(const char *str, const char *cp,
                                500                 :                :                              NumericVar *dest, const char **endptr,
                                501                 :                :                              Node *escontext);
                                502                 :                : static bool set_var_from_non_decimal_integer_str(const char *str,
                                503                 :                :                                                  const char *cp, int sign,
                                504                 :                :                                                  int base, NumericVar *dest,
                                505                 :                :                                                  const char **endptr,
                                506                 :                :                                                  Node *escontext);
                                507                 :                : static void set_var_from_num(Numeric num, NumericVar *dest);
                                508                 :                : static void init_var_from_num(Numeric num, NumericVar *dest);
                                509                 :                : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
                                510                 :                : static char *get_str_from_var(const NumericVar *var);
                                511                 :                : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
                                512                 :                : 
                                513                 :                : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
                                514                 :                : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
                                515                 :                : 
                                516                 :                : static Numeric duplicate_numeric(Numeric num);
                                517                 :                : static Numeric make_result(const NumericVar *var);
                                518                 :                : static Numeric make_result_opt_error(const NumericVar *var, bool *have_error);
                                519                 :                : 
                                520                 :                : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
                                521                 :                : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
                                522                 :                : 
                                523                 :                : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
                                524                 :                : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
                                525                 :                : static void int64_to_numericvar(int64 val, NumericVar *var);
                                526                 :                : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
                                527                 :                : #ifdef HAVE_INT128
                                528                 :                : static bool numericvar_to_int128(const NumericVar *var, int128 *result);
                                529                 :                : static void int128_to_numericvar(int128 val, NumericVar *var);
                                530                 :                : #endif
                                531                 :                : static double numericvar_to_double_no_overflow(const NumericVar *var);
                                532                 :                : 
                                533                 :                : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
                                534                 :                : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
                                535                 :                : static int  numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
                                536                 :                : static int  numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
                                537                 :                : 
                                538                 :                : static Datum numeric_abbrev_convert_var(const NumericVar *var,
                                539                 :                :                                         NumericSortSupport *nss);
                                540                 :                : 
                                541                 :                : static int  cmp_numerics(Numeric num1, Numeric num2);
                                542                 :                : static int  cmp_var(const NumericVar *var1, const NumericVar *var2);
                                543                 :                : static int  cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
                                544                 :                :                            int var1weight, int var1sign,
                                545                 :                :                            const NumericDigit *var2digits, int var2ndigits,
                                546                 :                :                            int var2weight, int var2sign);
                                547                 :                : static void add_var(const NumericVar *var1, const NumericVar *var2,
                                548                 :                :                     NumericVar *result);
                                549                 :                : static void sub_var(const NumericVar *var1, const NumericVar *var2,
                                550                 :                :                     NumericVar *result);
                                551                 :                : static void mul_var(const NumericVar *var1, const NumericVar *var2,
                                552                 :                :                     NumericVar *result,
                                553                 :                :                     int rscale);
                                554                 :                : static void div_var(const NumericVar *var1, const NumericVar *var2,
                                555                 :                :                     NumericVar *result,
                                556                 :                :                     int rscale, bool round);
                                557                 :                : static void div_var_fast(const NumericVar *var1, const NumericVar *var2,
                                558                 :                :                          NumericVar *result, int rscale, bool round);
                                559                 :                : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
                                560                 :                :                         NumericVar *result, int rscale, bool round);
                                561                 :                : #ifdef HAVE_INT128
                                562                 :                : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
                                563                 :                :                           NumericVar *result, int rscale, bool round);
                                564                 :                : #endif
                                565                 :                : static int  select_div_scale(const NumericVar *var1, const NumericVar *var2);
                                566                 :                : static void mod_var(const NumericVar *var1, const NumericVar *var2,
                                567                 :                :                     NumericVar *result);
                                568                 :                : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
                                569                 :                :                         NumericVar *quot, NumericVar *rem);
                                570                 :                : static void ceil_var(const NumericVar *var, NumericVar *result);
                                571                 :                : static void floor_var(const NumericVar *var, NumericVar *result);
                                572                 :                : 
                                573                 :                : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
                                574                 :                :                     NumericVar *result);
                                575                 :                : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
                                576                 :                : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
                                577                 :                : static int  estimate_ln_dweight(const NumericVar *var);
                                578                 :                : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
                                579                 :                : static void log_var(const NumericVar *base, const NumericVar *num,
                                580                 :                :                     NumericVar *result);
                                581                 :                : static void power_var(const NumericVar *base, const NumericVar *exp,
                                582                 :                :                       NumericVar *result);
                                583                 :                : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
                                584                 :                :                           NumericVar *result);
                                585                 :                : static void power_ten_int(int exp, NumericVar *result);
                                586                 :                : static void random_var(pg_prng_state *state, const NumericVar *rmin,
                                587                 :                :                        const NumericVar *rmax, NumericVar *result);
                                588                 :                : 
                                589                 :                : static int  cmp_abs(const NumericVar *var1, const NumericVar *var2);
                                590                 :                : static int  cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
                                591                 :                :                            int var1weight,
                                592                 :                :                            const NumericDigit *var2digits, int var2ndigits,
                                593                 :                :                            int var2weight);
                                594                 :                : static void add_abs(const NumericVar *var1, const NumericVar *var2,
                                595                 :                :                     NumericVar *result);
                                596                 :                : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
                                597                 :                :                     NumericVar *result);
                                598                 :                : static void round_var(NumericVar *var, int rscale);
                                599                 :                : static void trunc_var(NumericVar *var, int rscale);
                                600                 :                : static void strip_var(NumericVar *var);
                                601                 :                : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
                                602                 :                :                            const NumericVar *count_var, bool reversed_bounds,
                                603                 :                :                            NumericVar *result_var);
                                604                 :                : 
                                605                 :                : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
                                606                 :                : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
                                607                 :                : static void accum_sum_carry(NumericSumAccum *accum);
                                608                 :                : static void accum_sum_reset(NumericSumAccum *accum);
                                609                 :                : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
                                610                 :                : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
                                611                 :                : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
                                612                 :                : 
                                613                 :                : 
                                614                 :                : /* ----------------------------------------------------------------------
                                615                 :                :  *
                                616                 :                :  * Input-, output- and rounding-functions
                                617                 :                :  *
                                618                 :                :  * ----------------------------------------------------------------------
                                619                 :                :  */
                                620                 :                : 
                                621                 :                : 
                                622                 :                : /*
                                623                 :                :  * numeric_in() -
                                624                 :                :  *
                                625                 :                :  *  Input function for numeric data type
                                626                 :                :  */
                                627                 :                : Datum
 8706 tgl@sss.pgh.pa.us         628                 :CBC       53302 : numeric_in(PG_FUNCTION_ARGS)
                                629                 :                : {
                                630                 :          53302 :     char       *str = PG_GETARG_CSTRING(0);
                                631                 :                : #ifdef NOT_USED
                                632                 :                :     Oid         typelem = PG_GETARG_OID(1);
                                633                 :                : #endif
                                634                 :          53302 :     int32       typmod = PG_GETARG_INT32(2);
  492                           635                 :          53302 :     Node       *escontext = fcinfo->context;
                                636                 :                :     Numeric     res;
                                637                 :                :     const char *cp;
                                638                 :                :     const char *numstart;
                                639                 :                :     int         sign;
                                640                 :                : 
                                641                 :                :     /* Skip leading spaces */
 5485                           642                 :          53302 :     cp = str;
                                643         [ +  + ]:          53494 :     while (*cp)
                                644                 :                :     {
                                645         [ +  + ]:          53488 :         if (!isspace((unsigned char) *cp))
                                646                 :          53296 :             break;
                                647                 :            192 :         cp++;
                                648                 :                :     }
                                649                 :                : 
                                650                 :                :     /*
                                651                 :                :      * Process the number's sign. This duplicates logic in set_var_from_str(),
                                652                 :                :      * but it's worth doing here, since it simplifies the handling of
                                653                 :                :      * infinities and non-decimal integers.
                                654                 :                :      */
  447 dean.a.rasheed@gmail      655                 :          53302 :     numstart = cp;
                                656                 :          53302 :     sign = NUMERIC_POS;
                                657                 :                : 
                                658         [ +  + ]:          53302 :     if (*cp == '+')
                                659                 :             24 :         cp++;
                                660         [ +  + ]:          53278 :     else if (*cp == '-')
                                661                 :                :     {
                                662                 :           1846 :         sign = NUMERIC_NEG;
                                663                 :           1846 :         cp++;
                                664                 :                :     }
                                665                 :                : 
                                666                 :                :     /*
                                667                 :                :      * Check for NaN and infinities.  We recognize the same strings allowed by
                                668                 :                :      * float8in().
                                669                 :                :      *
                                670                 :                :      * Since all other legal inputs have a digit or a decimal point after the
                                671                 :                :      * sign, we need only check for NaN/infinity if that's not the case.
                                672                 :                :      */
                                673   [ +  +  +  + ]:          53302 :     if (!isdigit((unsigned char) *cp) && *cp != '.')
                                674                 :                :     {
                                675                 :                :         /*
                                676                 :                :          * The number must be NaN or infinity; anything else can only be a
                                677                 :                :          * syntax error. Note that NaN mustn't have a sign.
                                678                 :                :          */
                                679         [ +  + ]:            833 :         if (pg_strncasecmp(numstart, "NaN", 3) == 0)
                                680                 :                :         {
                                681                 :            289 :             res = make_result(&const_nan);
                                682                 :            289 :             cp = numstart + 3;
                                683                 :                :         }
                                684         [ +  + ]:            544 :         else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
                                685                 :                :         {
                                686         [ +  + ]:            198 :             res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
                                687                 :            198 :             cp += 8;
                                688                 :                :         }
                                689         [ +  + ]:            346 :         else if (pg_strncasecmp(cp, "inf", 3) == 0)
                                690                 :                :         {
                                691         [ +  + ]:            294 :             res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
                                692                 :            294 :             cp += 3;
                                693                 :                :         }
                                694                 :                :         else
                                695                 :             52 :             goto invalid_syntax;
                                696                 :                : 
                                697                 :                :         /*
                                698                 :                :          * Check for trailing junk; there should be nothing left but spaces.
                                699                 :                :          *
                                700                 :                :          * We intentionally do this check before applying the typmod because
                                701                 :                :          * we would like to throw any trailing-junk syntax error before any
                                702                 :                :          * semantic error resulting from apply_typmod_special().
                                703                 :                :          */
                                704         [ +  + ]:            802 :         while (*cp)
                                705                 :                :         {
                                706         [ -  + ]:             21 :             if (!isspace((unsigned char) *cp))
  447 dean.a.rasheed@gmail      707                 :UBC           0 :                 goto invalid_syntax;
  447 dean.a.rasheed@gmail      708                 :CBC          21 :             cp++;
                                709                 :                :         }
                                710                 :                : 
                                711         [ -  + ]:            781 :         if (!apply_typmod_special(res, typmod, escontext))
  447 dean.a.rasheed@gmail      712                 :UBC           0 :             PG_RETURN_NULL();
                                713                 :                :     }
                                714                 :                :     else
                                715                 :                :     {
                                716                 :                :         /*
                                717                 :                :          * We have a normal numeric value, which may be a non-decimal integer
                                718                 :                :          * or a regular decimal number.
                                719                 :                :          */
                                720                 :                :         NumericVar  value;
                                721                 :                :         int         base;
                                722                 :                :         bool        have_error;
                                723                 :                : 
 5485 tgl@sss.pgh.pa.us         724                 :CBC       52469 :         init_var(&value);
                                725                 :                : 
                                726                 :                :         /*
                                727                 :                :          * Determine the number's base by looking for a non-decimal prefix
                                728                 :                :          * indicator ("0x", "0o", or "0b").
                                729                 :                :          */
  447 dean.a.rasheed@gmail      730         [ +  + ]:          52469 :         if (cp[0] == '0')
                                731                 :                :         {
                                732   [ +  +  +  + ]:          13521 :             switch (cp[1])
                                733                 :                :             {
                                734                 :             36 :                 case 'x':
                                735                 :                :                 case 'X':
                                736                 :             36 :                     base = 16;
                                737                 :             36 :                     break;
                                738                 :             21 :                 case 'o':
                                739                 :                :                 case 'O':
                                740                 :             21 :                     base = 8;
                                741                 :             21 :                     break;
                                742                 :             21 :                 case 'b':
                                743                 :                :                 case 'B':
                                744                 :             21 :                     base = 2;
                                745                 :             21 :                     break;
                                746                 :          13443 :                 default:
                                747                 :          13443 :                     base = 10;
                                748                 :                :             }
                                749                 :                :         }
                                750                 :                :         else
                                751                 :          38948 :             base = 10;
                                752                 :                : 
                                753                 :                :         /* Parse the rest of the number and apply the sign */
                                754         [ +  + ]:          52469 :         if (base == 10)
                                755                 :                :         {
                                756         [ -  + ]:          52391 :             if (!set_var_from_str(str, cp, &value, &cp, escontext))
  447 dean.a.rasheed@gmail      757                 :UBC           0 :                 PG_RETURN_NULL();
  447 dean.a.rasheed@gmail      758                 :CBC       52367 :             value.sign = sign;
                                759                 :                :         }
                                760                 :                :         else
                                761                 :                :         {
                                762         [ -  + ]:             78 :             if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
                                763                 :                :                                                       &value, &cp, escontext))
  447 dean.a.rasheed@gmail      764                 :UBC           0 :                 PG_RETURN_NULL();
                                765                 :                :         }
                                766                 :                : 
                                767                 :                :         /*
                                768                 :                :          * Should be nothing left but spaces. As above, throw any typmod error
                                769                 :                :          * after finishing syntax check.
                                770                 :                :          */
 5485 tgl@sss.pgh.pa.us         771         [ +  + ]:CBC       52475 :         while (*cp)
                                772                 :                :         {
                                773         [ +  + ]:             75 :             if (!isspace((unsigned char) *cp))
  447 dean.a.rasheed@gmail      774                 :             36 :                 goto invalid_syntax;
 5485 tgl@sss.pgh.pa.us         775                 :             39 :             cp++;
                                776                 :                :         }
                                777                 :                : 
  492                           778         [ +  + ]:          52400 :         if (!apply_typmod(&value, typmod, escontext))
                                779                 :             12 :             PG_RETURN_NULL();
                                780                 :                : 
                                781                 :          52388 :         res = make_result_opt_error(&value, &have_error);
                                782                 :                : 
                                783         [ +  + ]:          52388 :         if (have_error)
                                784         [ +  + ]:              9 :             ereturn(escontext, (Datum) 0,
                                785                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                786                 :                :                      errmsg("value overflows numeric format")));
                                787                 :                : 
 5485                           788                 :          52379 :         free_var(&value);
                                789                 :                :     }
                                790                 :                : 
 8706                           791                 :          53160 :     PG_RETURN_NUMERIC(res);
                                792                 :                : 
  447 dean.a.rasheed@gmail      793                 :             88 : invalid_syntax:
                                794         [ +  + ]:             88 :     ereturn(escontext, (Datum) 0,
                                795                 :                :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                                796                 :                :              errmsg("invalid input syntax for type %s: \"%s\"",
                                797                 :                :                     "numeric", str)));
                                798                 :                : }
                                799                 :                : 
                                800                 :                : 
                                801                 :                : /*
                                802                 :                :  * numeric_out() -
                                803                 :                :  *
                                804                 :                :  *  Output function for numeric data type
                                805                 :                :  */
                                806                 :                : Datum
 8706 tgl@sss.pgh.pa.us         807                 :         392192 : numeric_out(PG_FUNCTION_ARGS)
                                808                 :                : {
                                809                 :         392192 :     Numeric     num = PG_GETARG_NUMERIC(0);
                                810                 :                :     NumericVar  x;
                                811                 :                :     char       *str;
                                812                 :                : 
                                813                 :                :     /*
                                814                 :                :      * Handle NaN and infinities
                                815                 :                :      */
 1362                           816         [ +  + ]:         392192 :     if (NUMERIC_IS_SPECIAL(num))
                                817                 :                :     {
                                818         [ +  + ]:           1740 :         if (NUMERIC_IS_PINF(num))
                                819                 :            499 :             PG_RETURN_CSTRING(pstrdup("Infinity"));
                                820         [ +  + ]:           1241 :         else if (NUMERIC_IS_NINF(num))
                                821                 :            308 :             PG_RETURN_CSTRING(pstrdup("-Infinity"));
                                822                 :                :         else
                                823                 :            933 :             PG_RETURN_CSTRING(pstrdup("NaN"));
                                824                 :                :     }
                                825                 :                : 
                                826                 :                :     /*
                                827                 :                :      * Get the number in the variable format.
                                828                 :                :      */
 4162 heikki.linnakangas@i      829                 :         390452 :     init_var_from_num(num, &x);
                                830                 :                : 
                                831                 :         390452 :     str = get_str_from_var(&x);
                                832                 :                : 
 8706 tgl@sss.pgh.pa.us         833                 :         390452 :     PG_RETURN_CSTRING(str);
                                834                 :                : }
                                835                 :                : 
                                836                 :                : /*
                                837                 :                :  * numeric_is_nan() -
                                838                 :                :  *
                                839                 :                :  *  Is Numeric value a NaN?
                                840                 :                :  */
                                841                 :                : bool
 5007 rhaas@postgresql.org      842                 :           6801 : numeric_is_nan(Numeric num)
                                843                 :                : {
                                844                 :           6801 :     return NUMERIC_IS_NAN(num);
                                845                 :                : }
                                846                 :                : 
                                847                 :                : /*
                                848                 :                :  * numeric_is_inf() -
                                849                 :                :  *
                                850                 :                :  *  Is Numeric value an infinity?
                                851                 :                :  */
                                852                 :                : bool
 1362 tgl@sss.pgh.pa.us         853                 :            156 : numeric_is_inf(Numeric num)
                                854                 :                : {
                                855                 :            156 :     return NUMERIC_IS_INF(num);
                                856                 :                : }
                                857                 :                : 
                                858                 :                : /*
                                859                 :                :  * numeric_is_integral() -
                                860                 :                :  *
                                861                 :                :  *  Is Numeric value integral?
                                862                 :                :  */
                                863                 :                : static bool
                                864                 :             33 : numeric_is_integral(Numeric num)
                                865                 :                : {
                                866                 :                :     NumericVar  arg;
                                867                 :                : 
                                868                 :                :     /* Reject NaN, but infinities are considered integral */
                                869         [ +  + ]:             33 :     if (NUMERIC_IS_SPECIAL(num))
                                870                 :                :     {
                                871         [ -  + ]:             15 :         if (NUMERIC_IS_NAN(num))
 1362 tgl@sss.pgh.pa.us         872                 :UBC           0 :             return false;
 1362 tgl@sss.pgh.pa.us         873                 :CBC          15 :         return true;
                                874                 :                :     }
                                875                 :                : 
                                876                 :                :     /* Integral if there are no digits to the right of the decimal point */
                                877                 :             18 :     init_var_from_num(num, &arg);
                                878                 :                : 
                                879   [ +  +  +  + ]:             18 :     return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
                                880                 :                : }
                                881                 :                : 
                                882                 :                : /*
                                883                 :                :  * make_numeric_typmod() -
                                884                 :                :  *
                                885                 :                :  *  Pack numeric precision and scale values into a typmod.  The upper 16 bits
                                886                 :                :  *  are used for the precision (though actually not all these bits are needed,
                                887                 :                :  *  since the maximum allowed precision is 1000).  The lower 16 bits are for
                                888                 :                :  *  the scale, but since the scale is constrained to the range [-1000, 1000],
                                889                 :                :  *  we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
                                890                 :                :  *  unset, for possible future use.
                                891                 :                :  *
                                892                 :                :  *  For purely historical reasons VARHDRSZ is then added to the result, thus
                                893                 :                :  *  the unused space in the upper 16 bits is not all as freely available as it
                                894                 :                :  *  might seem.  (We can't let the result overflow to a negative int32, as
                                895                 :                :  *  other parts of the system would interpret that as not-a-valid-typmod.)
                                896                 :                :  */
                                897                 :                : static inline int32
  993 dean.a.rasheed@gmail      898                 :            937 : make_numeric_typmod(int precision, int scale)
                                899                 :                : {
                                900                 :            937 :     return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
                                901                 :                : }
                                902                 :                : 
                                903                 :                : /*
                                904                 :                :  * Because of the offset, valid numeric typmods are at least VARHDRSZ
                                905                 :                :  */
                                906                 :                : static inline bool
                                907                 :          65122 : is_valid_numeric_typmod(int32 typmod)
                                908                 :                : {
                                909                 :          65122 :     return typmod >= (int32) VARHDRSZ;
                                910                 :                : }
                                911                 :                : 
                                912                 :                : /*
                                913                 :                :  * numeric_typmod_precision() -
                                914                 :                :  *
                                915                 :                :  *  Extract the precision from a numeric typmod --- see make_numeric_typmod().
                                916                 :                :  */
                                917                 :                : static inline int
                                918                 :          12302 : numeric_typmod_precision(int32 typmod)
                                919                 :                : {
                                920                 :          12302 :     return ((typmod - VARHDRSZ) >> 16) & 0xffff;
                                921                 :                : }
                                922                 :                : 
                                923                 :                : /*
                                924                 :                :  * numeric_typmod_scale() -
                                925                 :                :  *
                                926                 :                :  *  Extract the scale from a numeric typmod --- see make_numeric_typmod().
                                927                 :                :  *
                                928                 :                :  *  Note that the scale may be negative, so we must do sign extension when
                                929                 :                :  *  unpacking it.  We do this using the bit hack (x^1024)-1024, which sign
                                930                 :                :  *  extends an 11-bit two's complement number x.
                                931                 :                :  */
                                932                 :                : static inline int
                                933                 :           8535 : numeric_typmod_scale(int32 typmod)
                                934                 :                : {
                                935                 :           8535 :     return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
                                936                 :                : }
                                937                 :                : 
                                938                 :                : /*
                                939                 :                :  * numeric_maximum_size() -
                                940                 :                :  *
                                941                 :                :  *  Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
                                942                 :                :  */
                                943                 :                : int32
 5002 rhaas@postgresql.org      944                 :           3767 : numeric_maximum_size(int32 typmod)
                                945                 :                : {
                                946                 :                :     int         precision;
                                947                 :                :     int         numeric_digits;
                                948                 :                : 
  993 dean.a.rasheed@gmail      949         [ -  + ]:           3767 :     if (!is_valid_numeric_typmod(typmod))
 5007 rhaas@postgresql.org      950                 :UBC           0 :         return -1;
                                951                 :                : 
                                952                 :                :     /* precision (ie, max # of digits) is in upper bits of typmod */
  993 dean.a.rasheed@gmail      953                 :CBC        3767 :     precision = numeric_typmod_precision(typmod);
                                954                 :                : 
                                955                 :                :     /*
                                956                 :                :      * This formula computes the maximum number of NumericDigits we could need
                                957                 :                :      * in order to store the specified number of decimal digits. Because the
                                958                 :                :      * weight is stored as a number of NumericDigits rather than a number of
                                959                 :                :      * decimal digits, it's possible that the first NumericDigit will contain
                                960                 :                :      * only a single decimal digit.  Thus, the first two decimal digits can
                                961                 :                :      * require two NumericDigits to store, but it isn't until we reach
                                962                 :                :      * DEC_DIGITS + 2 decimal digits that we potentially need a third
                                963                 :                :      * NumericDigit.
                                964                 :                :      */
 5002 rhaas@postgresql.org      965                 :           3767 :     numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
                                966                 :                : 
                                967                 :                :     /*
                                968                 :                :      * In most cases, the size of a numeric will be smaller than the value
                                969                 :                :      * computed below, because the varlena header will typically get toasted
                                970                 :                :      * down to a single byte before being stored on disk, and it may also be
                                971                 :                :      * possible to use a short numeric header.  But our job here is to compute
                                972                 :                :      * the worst case.
                                973                 :                :      */
                                974                 :           3767 :     return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
                                975                 :                : }
                                976                 :                : 
                                977                 :                : /*
                                978                 :                :  * numeric_out_sci() -
                                979                 :                :  *
                                980                 :                :  *  Output function for numeric data type in scientific notation.
                                981                 :                :  */
                                982                 :                : char *
 5361 tgl@sss.pgh.pa.us         983                 :            117 : numeric_out_sci(Numeric num, int scale)
                                984                 :                : {
                                985                 :                :     NumericVar  x;
                                986                 :                :     char       *str;
                                987                 :                : 
                                988                 :                :     /*
                                989                 :                :      * Handle NaN and infinities
                                990                 :                :      */
 1362                           991         [ +  + ]:            117 :     if (NUMERIC_IS_SPECIAL(num))
                                992                 :                :     {
                                993         [ +  + ]:              9 :         if (NUMERIC_IS_PINF(num))
                                994                 :              3 :             return pstrdup("Infinity");
                                995         [ +  + ]:              6 :         else if (NUMERIC_IS_NINF(num))
                                996                 :              3 :             return pstrdup("-Infinity");
                                997                 :                :         else
                                998                 :              3 :             return pstrdup("NaN");
                                999                 :                :     }
                               1000                 :                : 
 4162 heikki.linnakangas@i     1001                 :            108 :     init_var_from_num(num, &x);
                               1002                 :                : 
 5361 tgl@sss.pgh.pa.us        1003                 :            108 :     str = get_str_from_var_sci(&x, scale);
                               1004                 :                : 
                               1005                 :            108 :     return str;
                               1006                 :                : }
                               1007                 :                : 
                               1008                 :                : /*
                               1009                 :                :  * numeric_normalize() -
                               1010                 :                :  *
                               1011                 :                :  *  Output function for numeric data type, suppressing insignificant trailing
                               1012                 :                :  *  zeroes and then any trailing decimal point.  The intent of this is to
                               1013                 :                :  *  produce strings that are equal if and only if the input numeric values
                               1014                 :                :  *  compare equal.
                               1015                 :                :  */
                               1016                 :                : char *
 3675 andrew@dunslane.net      1017                 :           6483 : numeric_normalize(Numeric num)
                               1018                 :                : {
                               1019                 :                :     NumericVar  x;
                               1020                 :                :     char       *str;
                               1021                 :                :     int         last;
                               1022                 :                : 
                               1023                 :                :     /*
                               1024                 :                :      * Handle NaN and infinities
                               1025                 :                :      */
 1362 tgl@sss.pgh.pa.us        1026         [ -  + ]:           6483 :     if (NUMERIC_IS_SPECIAL(num))
                               1027                 :                :     {
 1362 tgl@sss.pgh.pa.us        1028         [ #  # ]:UBC           0 :         if (NUMERIC_IS_PINF(num))
                               1029                 :              0 :             return pstrdup("Infinity");
                               1030         [ #  # ]:              0 :         else if (NUMERIC_IS_NINF(num))
                               1031                 :              0 :             return pstrdup("-Infinity");
                               1032                 :                :         else
                               1033                 :              0 :             return pstrdup("NaN");
                               1034                 :                :     }
                               1035                 :                : 
 3675 andrew@dunslane.net      1036                 :CBC        6483 :     init_var_from_num(num, &x);
                               1037                 :                : 
                               1038                 :           6483 :     str = get_str_from_var(&x);
                               1039                 :                : 
                               1040                 :                :     /* If there's no decimal point, there's certainly nothing to remove. */
 3447 tgl@sss.pgh.pa.us        1041         [ +  + ]:           6483 :     if (strchr(str, '.') != NULL)
                               1042                 :                :     {
                               1043                 :                :         /*
                               1044                 :                :          * Back up over trailing fractional zeroes.  Since there is a decimal
                               1045                 :                :          * point, this loop will terminate safely.
                               1046                 :                :          */
                               1047                 :             21 :         last = strlen(str) - 1;
                               1048         [ +  + ]:             42 :         while (str[last] == '0')
                               1049                 :             21 :             last--;
                               1050                 :                : 
                               1051                 :                :         /* We want to get rid of the decimal point too, if it's now last. */
                               1052         [ +  - ]:             21 :         if (str[last] == '.')
                               1053                 :             21 :             last--;
                               1054                 :                : 
                               1055                 :                :         /* Delete whatever we backed up over. */
                               1056                 :             21 :         str[last + 1] = '\0';
                               1057                 :                :     }
                               1058                 :                : 
 3675 andrew@dunslane.net      1059                 :           6483 :     return str;
                               1060                 :                : }
                               1061                 :                : 
                               1062                 :                : /*
                               1063                 :                :  *      numeric_recv            - converts external binary format to numeric
                               1064                 :                :  *
                               1065                 :                :  * External format is a sequence of int16's:
                               1066                 :                :  * ndigits, weight, sign, dscale, NumericDigits.
                               1067                 :                :  */
                               1068                 :                : Datum
 7643 tgl@sss.pgh.pa.us        1069                 :             51 : numeric_recv(PG_FUNCTION_ARGS)
                               1070                 :                : {
                               1071                 :             51 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
                               1072                 :                : 
                               1073                 :                : #ifdef NOT_USED
                               1074                 :                :     Oid         typelem = PG_GETARG_OID(1);
                               1075                 :                : #endif
 6853                          1076                 :             51 :     int32       typmod = PG_GETARG_INT32(2);
                               1077                 :                :     NumericVar  value;
                               1078                 :                :     Numeric     res;
                               1079                 :                :     int         len,
                               1080                 :                :                 i;
                               1081                 :                : 
 7643                          1082                 :             51 :     init_var(&value);
                               1083                 :                : 
                               1084                 :             51 :     len = (uint16) pq_getmsgint(buf, sizeof(uint16));
                               1085                 :                : 
                               1086                 :             51 :     alloc_var(&value, len);
                               1087                 :                : 
                               1088                 :             51 :     value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
                               1089                 :                :     /* we allow any int16 for weight --- OK? */
                               1090                 :                : 
                               1091                 :             51 :     value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
                               1092         [ -  + ]:             51 :     if (!(value.sign == NUMERIC_POS ||
 7643 tgl@sss.pgh.pa.us        1093         [ #  # ]:UBC           0 :           value.sign == NUMERIC_NEG ||
 1362                          1094         [ #  # ]:              0 :           value.sign == NUMERIC_NAN ||
                               1095         [ #  # ]:              0 :           value.sign == NUMERIC_PINF ||
                               1096         [ #  # ]:              0 :           value.sign == NUMERIC_NINF))
 7567                          1097         [ #  # ]:              0 :         ereport(ERROR,
                               1098                 :                :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1099                 :                :                  errmsg("invalid sign in external \"numeric\" value")));
                               1100                 :                : 
 7643 tgl@sss.pgh.pa.us        1101                 :CBC          51 :     value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
 3422                          1102         [ -  + ]:             51 :     if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
 3422 tgl@sss.pgh.pa.us        1103         [ #  # ]:UBC           0 :         ereport(ERROR,
                               1104                 :                :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1105                 :                :                  errmsg("invalid scale in external \"numeric\" value")));
                               1106                 :                : 
 7643 tgl@sss.pgh.pa.us        1107         [ +  + ]:CBC         137 :     for (i = 0; i < len; i++)
                               1108                 :                :     {
 7559 bruce@momjian.us         1109                 :             86 :         NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
                               1110                 :                : 
 7643 tgl@sss.pgh.pa.us        1111   [ +  -  -  + ]:             86 :         if (d < 0 || d >= NBASE)
 7567 tgl@sss.pgh.pa.us        1112         [ #  # ]:UBC           0 :             ereport(ERROR,
                               1113                 :                :                     (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1114                 :                :                      errmsg("invalid digit in external \"numeric\" value")));
 7643 tgl@sss.pgh.pa.us        1115                 :CBC          86 :         value.digits[i] = d;
                               1116                 :                :     }
                               1117                 :                : 
                               1118                 :                :     /*
                               1119                 :                :      * If the given dscale would hide any digits, truncate those digits away.
                               1120                 :                :      * We could alternatively throw an error, but that would take a bunch of
                               1121                 :                :      * extra code (about as much as trunc_var involves), and it might cause
                               1122                 :                :      * client compatibility issues.  Be careful not to apply trunc_var to
                               1123                 :                :      * special values, as it could do the wrong thing; we don't need it
                               1124                 :                :      * anyway, since make_result will ignore all but the sign field.
                               1125                 :                :      *
                               1126                 :                :      * After doing that, be sure to check the typmod restriction.
                               1127                 :                :      */
 1362                          1128         [ -  + ]:             51 :     if (value.sign == NUMERIC_POS ||
 1362 tgl@sss.pgh.pa.us        1129         [ #  # ]:UBC           0 :         value.sign == NUMERIC_NEG)
                               1130                 :                :     {
 1362 tgl@sss.pgh.pa.us        1131                 :CBC          51 :         trunc_var(&value, value.dscale);
                               1132                 :                : 
  492                          1133                 :             51 :         (void) apply_typmod(&value, typmod, NULL);
                               1134                 :                : 
 1362                          1135                 :             51 :         res = make_result(&value);
                               1136                 :                :     }
                               1137                 :                :     else
                               1138                 :                :     {
                               1139                 :                :         /* apply_typmod_special wants us to make the Numeric first */
 1362 tgl@sss.pgh.pa.us        1140                 :UBC           0 :         res = make_result(&value);
                               1141                 :                : 
  492                          1142                 :              0 :         (void) apply_typmod_special(res, typmod, NULL);
                               1143                 :                :     }
                               1144                 :                : 
 7643 tgl@sss.pgh.pa.us        1145                 :CBC          51 :     free_var(&value);
                               1146                 :                : 
                               1147                 :             51 :     PG_RETURN_NUMERIC(res);
                               1148                 :                : }
                               1149                 :                : 
                               1150                 :                : /*
                               1151                 :                :  *      numeric_send            - converts numeric to binary format
                               1152                 :                :  */
                               1153                 :                : Datum
                               1154                 :             35 : numeric_send(PG_FUNCTION_ARGS)
                               1155                 :                : {
                               1156                 :             35 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1157                 :                :     NumericVar  x;
                               1158                 :                :     StringInfoData buf;
                               1159                 :                :     int         i;
                               1160                 :                : 
 4162 heikki.linnakangas@i     1161                 :             35 :     init_var_from_num(num, &x);
                               1162                 :                : 
 7643 tgl@sss.pgh.pa.us        1163                 :             35 :     pq_begintypsend(&buf);
                               1164                 :                : 
 2377 andres@anarazel.de       1165                 :             35 :     pq_sendint16(&buf, x.ndigits);
                               1166                 :             35 :     pq_sendint16(&buf, x.weight);
                               1167                 :             35 :     pq_sendint16(&buf, x.sign);
                               1168                 :             35 :     pq_sendint16(&buf, x.dscale);
 7643 tgl@sss.pgh.pa.us        1169         [ +  + ]:             97 :     for (i = 0; i < x.ndigits; i++)
 2377 andres@anarazel.de       1170                 :             62 :         pq_sendint16(&buf, x.digits[i]);
                               1171                 :                : 
 7643 tgl@sss.pgh.pa.us        1172                 :             35 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
                               1173                 :                : }
                               1174                 :                : 
                               1175                 :                : 
                               1176                 :                : /*
                               1177                 :                :  * numeric_support()
                               1178                 :                :  *
                               1179                 :                :  * Planner support function for the numeric() length coercion function.
                               1180                 :                :  *
                               1181                 :                :  * Flatten calls that solely represent increases in allowable precision.
                               1182                 :                :  * Scale changes mutate every datum, so they are unoptimizable.  Some values,
                               1183                 :                :  * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
                               1184                 :                :  * an unconstrained numeric to any constrained numeric is also unoptimizable.
                               1185                 :                :  */
                               1186                 :                : Datum
 1891                          1187                 :            258 : numeric_support(PG_FUNCTION_ARGS)
                               1188                 :                : {
                               1189                 :            258 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
 4450 rhaas@postgresql.org     1190                 :            258 :     Node       *ret = NULL;
                               1191                 :                : 
 1891 tgl@sss.pgh.pa.us        1192         [ +  + ]:            258 :     if (IsA(rawreq, SupportRequestSimplify))
                               1193                 :                :     {
                               1194                 :            114 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
                               1195                 :            114 :         FuncExpr   *expr = req->fcall;
                               1196                 :                :         Node       *typmod;
                               1197                 :                : 
                               1198         [ -  + ]:            114 :         Assert(list_length(expr->args) >= 2);
                               1199                 :                : 
                               1200                 :            114 :         typmod = (Node *) lsecond(expr->args);
                               1201                 :                : 
 1429                          1202   [ +  -  +  - ]:            114 :         if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
                               1203                 :                :         {
 1891                          1204                 :            114 :             Node       *source = (Node *) linitial(expr->args);
                               1205                 :            114 :             int32       old_typmod = exprTypmod(source);
                               1206                 :            114 :             int32       new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
  993 dean.a.rasheed@gmail     1207                 :            114 :             int32       old_scale = numeric_typmod_scale(old_typmod);
                               1208                 :            114 :             int32       new_scale = numeric_typmod_scale(new_typmod);
                               1209                 :            114 :             int32       old_precision = numeric_typmod_precision(old_typmod);
                               1210                 :            114 :             int32       new_precision = numeric_typmod_precision(new_typmod);
                               1211                 :                : 
                               1212                 :                :             /*
                               1213                 :                :              * If new_typmod is invalid, the destination is unconstrained;
                               1214                 :                :              * that's always OK.  If old_typmod is valid, the source is
                               1215                 :                :              * constrained, and we're OK if the scale is unchanged and the
                               1216                 :                :              * precision is not decreasing.  See further notes in function
                               1217                 :                :              * header comment.
                               1218                 :                :              */
                               1219   [ +  -  +  + ]:            228 :             if (!is_valid_numeric_typmod(new_typmod) ||
                               1220         [ +  + ]:            120 :                 (is_valid_numeric_typmod(old_typmod) &&
 1891 tgl@sss.pgh.pa.us        1221         [ +  - ]:              3 :                  new_scale == old_scale && new_precision >= old_precision))
                               1222                 :              3 :                 ret = relabel_to_typmod(source, new_typmod);
                               1223                 :                :         }
                               1224                 :                :     }
                               1225                 :                : 
 4450 rhaas@postgresql.org     1226                 :            258 :     PG_RETURN_POINTER(ret);
                               1227                 :                : }
                               1228                 :                : 
                               1229                 :                : /*
                               1230                 :                :  * numeric() -
                               1231                 :                :  *
                               1232                 :                :  *  This is a special function called by the Postgres database system
                               1233                 :                :  *  before a value is stored in a tuple's attribute. The precision and
                               1234                 :                :  *  scale of the attribute have to be applied on the value.
                               1235                 :                :  */
                               1236                 :                : Datum
 5995 bruce@momjian.us         1237                 :           5881 : numeric     (PG_FUNCTION_ARGS)
                               1238                 :                : {
 8706 tgl@sss.pgh.pa.us        1239                 :           5881 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1240                 :           5881 :     int32       typmod = PG_GETARG_INT32(1);
                               1241                 :                :     Numeric     new;
                               1242                 :                :     int         precision;
                               1243                 :                :     int         scale;
                               1244                 :                :     int         ddigits;
                               1245                 :                :     int         maxdigits;
                               1246                 :                :     int         dscale;
                               1247                 :                :     NumericVar  var;
                               1248                 :                : 
                               1249                 :                :     /*
                               1250                 :                :      * Handle NaN and infinities: if apply_typmod_special doesn't complain,
                               1251                 :                :      * just return a copy of the input.
                               1252                 :                :      */
 1362                          1253         [ +  + ]:           5881 :     if (NUMERIC_IS_SPECIAL(num))
                               1254                 :                :     {
  492                          1255                 :            105 :         (void) apply_typmod_special(num, typmod, NULL);
 1362                          1256                 :             96 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1257                 :                :     }
                               1258                 :                : 
                               1259                 :                :     /*
                               1260                 :                :      * If the value isn't a valid type modifier, simply return a copy of the
                               1261                 :                :      * input value
                               1262                 :                :      */
  993 dean.a.rasheed@gmail     1263         [ -  + ]:           5776 :     if (!is_valid_numeric_typmod(typmod))
 1362 tgl@sss.pgh.pa.us        1264                 :UBC           0 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1265                 :                : 
                               1266                 :                :     /*
                               1267                 :                :      * Get the precision and scale out of the typmod value
                               1268                 :                :      */
  993 dean.a.rasheed@gmail     1269                 :CBC        5776 :     precision = numeric_typmod_precision(typmod);
                               1270                 :           5776 :     scale = numeric_typmod_scale(typmod);
 7695 tgl@sss.pgh.pa.us        1271                 :           5776 :     maxdigits = precision - scale;
                               1272                 :                : 
                               1273                 :                :     /* The target display scale is non-negative */
  993 dean.a.rasheed@gmail     1274                 :           5776 :     dscale = Max(scale, 0);
                               1275                 :                : 
                               1276                 :                :     /*
                               1277                 :                :      * If the number is certainly in bounds and due to the target scale no
                               1278                 :                :      * rounding could be necessary, just make a copy of the input and modify
                               1279                 :                :      * its scale fields, unless the larger scale forces us to abandon the
                               1280                 :                :      * short representation.  (Note we assume the existing dscale is
                               1281                 :                :      * honest...)
                               1282                 :                :      */
 5003 rhaas@postgresql.org     1283   [ +  +  +  + ]:           5776 :     ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
                               1284   [ +  +  +  +  :           5776 :     if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
                                              +  + ]
  993 dean.a.rasheed@gmail     1285   [ +  -  +  -  :           3565 :         && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
                                     +  +  +  -  -  
                                     -  +  -  +  +  
                                        -  +  -  - ]
 4753 bruce@momjian.us         1286         [ #  # ]:UBC           0 :             || !NUMERIC_IS_SHORT(num)))
                               1287                 :                :     {
 1362 tgl@sss.pgh.pa.us        1288                 :CBC        3565 :         new = duplicate_numeric(num);
 5003 rhaas@postgresql.org     1289         [ +  - ]:           3565 :         if (NUMERIC_IS_SHORT(num))
                               1290                 :           3565 :             new->choice.n_short.n_header =
                               1291                 :           3565 :                 (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
  993 dean.a.rasheed@gmail     1292                 :           3565 :                 | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
                               1293                 :                :         else
 5003 rhaas@postgresql.org     1294   [ #  #  #  # ]:UBC           0 :             new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
  993 dean.a.rasheed@gmail     1295                 :              0 :                 ((uint16) dscale & NUMERIC_DSCALE_MASK);
 8706 tgl@sss.pgh.pa.us        1296                 :CBC        3565 :         PG_RETURN_NUMERIC(new);
                               1297                 :                :     }
                               1298                 :                : 
                               1299                 :                :     /*
                               1300                 :                :      * We really need to fiddle with things - unpack the number into a
                               1301                 :                :      * variable and let apply_typmod() do it.
                               1302                 :                :      */
 9237 JanWieck@Yahoo.com       1303                 :           2211 :     init_var(&var);
                               1304                 :                : 
                               1305                 :           2211 :     set_var_from_num(num, &var);
  492 tgl@sss.pgh.pa.us        1306                 :           2211 :     (void) apply_typmod(&var, typmod, NULL);
 9237 JanWieck@Yahoo.com       1307                 :           2181 :     new = make_result(&var);
                               1308                 :                : 
                               1309                 :           2181 :     free_var(&var);
                               1310                 :                : 
 8706 tgl@sss.pgh.pa.us        1311                 :           2181 :     PG_RETURN_NUMERIC(new);
                               1312                 :                : }
                               1313                 :                : 
                               1314                 :                : Datum
 6315                          1315                 :            958 : numerictypmodin(PG_FUNCTION_ARGS)
                               1316                 :                : {
 5995 bruce@momjian.us         1317                 :            958 :     ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
                               1318                 :                :     int32      *tl;
                               1319                 :                :     int         n;
                               1320                 :                :     int32       typmod;
                               1321                 :                : 
 6148 tgl@sss.pgh.pa.us        1322                 :            958 :     tl = ArrayGetIntegerTypmods(ta, &n);
                               1323                 :                : 
 6315                          1324         [ +  + ]:            958 :     if (n == 2)
                               1325                 :                :     {
                               1326   [ +  +  +  + ]:            950 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
 6315 tgl@sss.pgh.pa.us        1327         [ +  - ]:GBC           9 :             ereport(ERROR,
                               1328                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1329                 :                :                      errmsg("NUMERIC precision %d must be between 1 and %d",
                               1330                 :                :                             tl[0], NUMERIC_MAX_PRECISION)));
  993 dean.a.rasheed@gmail     1331   [ +  +  +  + ]:CBC         941 :         if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
 6315 tgl@sss.pgh.pa.us        1332         [ +  - ]:GBC           6 :             ereport(ERROR,
                               1333                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1334                 :                :                      errmsg("NUMERIC scale %d must be between %d and %d",
                               1335                 :                :                             tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
  993 dean.a.rasheed@gmail     1336                 :CBC         935 :         typmod = make_numeric_typmod(tl[0], tl[1]);
                               1337                 :                :     }
 6315 tgl@sss.pgh.pa.us        1338         [ +  + ]:              8 :     else if (n == 1)
                               1339                 :                :     {
                               1340   [ +  -  -  + ]:              2 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
 6315 tgl@sss.pgh.pa.us        1341         [ #  # ]:UBC           0 :             ereport(ERROR,
                               1342                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1343                 :                :                      errmsg("NUMERIC precision %d must be between 1 and %d",
                               1344                 :                :                             tl[0], NUMERIC_MAX_PRECISION)));
                               1345                 :                :         /* scale defaults to zero */
  993 dean.a.rasheed@gmail     1346                 :CBC           2 :         typmod = make_numeric_typmod(tl[0], 0);
                               1347                 :                :     }
                               1348                 :                :     else
                               1349                 :                :     {
 6315 tgl@sss.pgh.pa.us        1350         [ +  - ]:              6 :         ereport(ERROR,
                               1351                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1352                 :                :                  errmsg("invalid NUMERIC type modifier")));
                               1353                 :                :         typmod = 0;             /* keep compiler quiet */
                               1354                 :                :     }
                               1355                 :                : 
                               1356                 :            937 :     PG_RETURN_INT32(typmod);
                               1357                 :                : }
                               1358                 :                : 
                               1359                 :                : Datum
                               1360                 :            188 : numerictypmodout(PG_FUNCTION_ARGS)
                               1361                 :                : {
 5995 bruce@momjian.us         1362                 :            188 :     int32       typmod = PG_GETARG_INT32(0);
                               1363                 :            188 :     char       *res = (char *) palloc(64);
                               1364                 :                : 
  993 dean.a.rasheed@gmail     1365         [ +  - ]:            188 :     if (is_valid_numeric_typmod(typmod))
 6315 tgl@sss.pgh.pa.us        1366                 :            188 :         snprintf(res, 64, "(%d,%d)",
                               1367                 :                :                  numeric_typmod_precision(typmod),
                               1368                 :                :                  numeric_typmod_scale(typmod));
                               1369                 :                :     else
 6315 tgl@sss.pgh.pa.us        1370                 :UBC           0 :         *res = '\0';
                               1371                 :                : 
 6315 tgl@sss.pgh.pa.us        1372                 :CBC         188 :     PG_RETURN_CSTRING(res);
                               1373                 :                : }
                               1374                 :                : 
                               1375                 :                : 
                               1376                 :                : /* ----------------------------------------------------------------------
                               1377                 :                :  *
                               1378                 :                :  * Sign manipulation, rounding and the like
                               1379                 :                :  *
                               1380                 :                :  * ----------------------------------------------------------------------
                               1381                 :                :  */
                               1382                 :                : 
                               1383                 :                : Datum
 8660                          1384                 :           9753 : numeric_abs(PG_FUNCTION_ARGS)
                               1385                 :                : {
                               1386                 :           9753 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1387                 :                :     Numeric     res;
                               1388                 :                : 
                               1389                 :                :     /*
                               1390                 :                :      * Do it the easy way directly on the packed format
                               1391                 :                :      */
 1362                          1392                 :           9753 :     res = duplicate_numeric(num);
                               1393                 :                : 
 5003 rhaas@postgresql.org     1394         [ +  + ]:           9753 :     if (NUMERIC_IS_SHORT(num))
                               1395                 :           9720 :         res->choice.n_short.n_header =
                               1396                 :           9720 :             num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
 1362 tgl@sss.pgh.pa.us        1397         [ +  + ]:             33 :     else if (NUMERIC_IS_SPECIAL(num))
                               1398                 :                :     {
                               1399                 :                :         /* This changes -Inf to Inf, and doesn't affect NaN */
                               1400                 :              9 :         res->choice.n_short.n_header =
                               1401                 :              9 :             num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
                               1402                 :                :     }
                               1403                 :                :     else
 5003 rhaas@postgresql.org     1404         [ -  + ]:             24 :         res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
                               1405                 :                : 
 8660 tgl@sss.pgh.pa.us        1406                 :           9753 :     PG_RETURN_NUMERIC(res);
                               1407                 :                : }
                               1408                 :                : 
                               1409                 :                : 
                               1410                 :                : Datum
                               1411                 :            442 : numeric_uminus(PG_FUNCTION_ARGS)
                               1412                 :                : {
                               1413                 :            442 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1414                 :                :     Numeric     res;
                               1415                 :                : 
                               1416                 :                :     /*
                               1417                 :                :      * Do it the easy way directly on the packed format
                               1418                 :                :      */
 1362                          1419                 :            442 :     res = duplicate_numeric(num);
                               1420                 :                : 
                               1421         [ +  + ]:            442 :     if (NUMERIC_IS_SPECIAL(num))
                               1422                 :                :     {
                               1423                 :                :         /* Flip the sign, if it's Inf or -Inf */
                               1424         [ +  + ]:             63 :         if (!NUMERIC_IS_NAN(num))
                               1425                 :             42 :             res->choice.n_short.n_header =
                               1426                 :             42 :                 num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
                               1427                 :                :     }
                               1428                 :                : 
                               1429                 :                :     /*
                               1430                 :                :      * The packed format is known to be totally zero digit trimmed always. So
                               1431                 :                :      * once we've eliminated specials, we can identify a zero by the fact that
                               1432                 :                :      * there are no digits at all. Do nothing to a zero.
                               1433                 :                :      */
                               1434   [ +  -  +  + ]:            379 :     else if (NUMERIC_NDIGITS(num) != 0)
                               1435                 :                :     {
                               1436                 :                :         /* Else, flip the sign */
 5003 rhaas@postgresql.org     1437         [ +  - ]:            322 :         if (NUMERIC_IS_SHORT(num))
                               1438                 :            322 :             res->choice.n_short.n_header =
                               1439                 :            322 :                 num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
 5003 rhaas@postgresql.org     1440   [ #  #  #  #  :UBC           0 :         else if (NUMERIC_SIGN(num) == NUMERIC_POS)
                                              #  # ]
                               1441                 :              0 :             res->choice.n_long.n_sign_dscale =
                               1442         [ #  # ]:              0 :                 NUMERIC_NEG | NUMERIC_DSCALE(num);
                               1443                 :                :         else
                               1444                 :              0 :             res->choice.n_long.n_sign_dscale =
                               1445         [ #  # ]:              0 :                 NUMERIC_POS | NUMERIC_DSCALE(num);
                               1446                 :                :     }
                               1447                 :                : 
 8660 tgl@sss.pgh.pa.us        1448                 :CBC         442 :     PG_RETURN_NUMERIC(res);
                               1449                 :                : }
                               1450                 :                : 
                               1451                 :                : 
                               1452                 :                : Datum
 8347 bruce@momjian.us         1453                 :            249 : numeric_uplus(PG_FUNCTION_ARGS)
                               1454                 :                : {
                               1455                 :            249 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1456                 :                : 
 1362 tgl@sss.pgh.pa.us        1457                 :            249 :     PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1458                 :                : }
                               1459                 :                : 
                               1460                 :                : 
                               1461                 :                : /*
                               1462                 :                :  * numeric_sign_internal() -
                               1463                 :                :  *
                               1464                 :                :  * Returns -1 if the argument is less than 0, 0 if the argument is equal
                               1465                 :                :  * to 0, and 1 if the argument is greater than zero.  Caller must have
                               1466                 :                :  * taken care of the NaN case, but we can handle infinities here.
                               1467                 :                :  */
                               1468                 :                : static int
                               1469                 :           1773 : numeric_sign_internal(Numeric num)
                               1470                 :                : {
                               1471         [ +  + ]:           1773 :     if (NUMERIC_IS_SPECIAL(num))
                               1472                 :                :     {
                               1473         [ -  + ]:            156 :         Assert(!NUMERIC_IS_NAN(num));
                               1474                 :                :         /* Must be Inf or -Inf */
                               1475         [ +  + ]:            156 :         if (NUMERIC_IS_PINF(num))
                               1476                 :             93 :             return 1;
                               1477                 :                :         else
                               1478                 :             63 :             return -1;
                               1479                 :                :     }
                               1480                 :                : 
                               1481                 :                :     /*
                               1482                 :                :      * The packed format is known to be totally zero digit trimmed always. So
                               1483                 :                :      * once we've eliminated specials, we can identify a zero by the fact that
                               1484                 :                :      * there are no digits at all.
                               1485                 :                :      */
                               1486   [ +  +  +  + ]:           1617 :     else if (NUMERIC_NDIGITS(num) == 0)
                               1487                 :            114 :         return 0;
                               1488   [ +  +  -  +  :           1503 :     else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
                                              +  + ]
                               1489                 :            363 :         return -1;
                               1490                 :                :     else
                               1491                 :           1140 :         return 1;
                               1492                 :                : }
                               1493                 :                : 
                               1494                 :                : /*
                               1495                 :                :  * numeric_sign() -
                               1496                 :                :  *
                               1497                 :                :  * returns -1 if the argument is less than 0, 0 if the argument is equal
                               1498                 :                :  * to 0, and 1 if the argument is greater than zero.
                               1499                 :                :  */
                               1500                 :                : Datum
 8660                          1501                 :             24 : numeric_sign(PG_FUNCTION_ARGS)
                               1502                 :                : {
                               1503                 :             24 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1504                 :                : 
                               1505                 :                :     /*
                               1506                 :                :      * Handle NaN (infinities can be handled normally)
                               1507                 :                :      */
 9237 JanWieck@Yahoo.com       1508         [ +  + ]:             24 :     if (NUMERIC_IS_NAN(num))
 8660 tgl@sss.pgh.pa.us        1509                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               1510                 :                : 
 1362                          1511   [ +  +  +  - ]:             21 :     switch (numeric_sign_internal(num))
                               1512                 :                :     {
                               1513                 :              3 :         case 0:
                               1514                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               1515                 :              9 :         case 1:
                               1516                 :              9 :             PG_RETURN_NUMERIC(make_result(&const_one));
                               1517                 :              9 :         case -1:
                               1518                 :              9 :             PG_RETURN_NUMERIC(make_result(&const_minus_one));
                               1519                 :                :     }
                               1520                 :                : 
 1362 tgl@sss.pgh.pa.us        1521                 :UBC           0 :     Assert(false);
                               1522                 :                :     return (Datum) 0;
                               1523                 :                : }
                               1524                 :                : 
                               1525                 :                : 
                               1526                 :                : /*
                               1527                 :                :  * numeric_round() -
                               1528                 :                :  *
                               1529                 :                :  *  Round a value to have 'scale' digits after the decimal point.
                               1530                 :                :  *  We allow negative 'scale', implying rounding before the decimal
                               1531                 :                :  *  point --- Oracle interprets rounding that way.
                               1532                 :                :  */
                               1533                 :                : Datum
 8706 tgl@sss.pgh.pa.us        1534                 :CBC        3871 : numeric_round(PG_FUNCTION_ARGS)
                               1535                 :                : {
                               1536                 :           3871 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1537                 :           3871 :     int32       scale = PG_GETARG_INT32(1);
                               1538                 :                :     Numeric     res;
                               1539                 :                :     NumericVar  arg;
                               1540                 :                : 
                               1541                 :                :     /*
                               1542                 :                :      * Handle NaN and infinities
                               1543                 :                :      */
 1362                          1544         [ +  + ]:           3871 :     if (NUMERIC_IS_SPECIAL(num))
                               1545                 :             48 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1546                 :                : 
                               1547                 :                :     /*
                               1548                 :                :      * Limit the scale value to avoid possible overflow in calculations
                               1549                 :                :      */
 7865                          1550                 :           3823 :     scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
                               1551                 :           3823 :     scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
                               1552                 :                : 
                               1553                 :                :     /*
                               1554                 :                :      * Unpack the argument and round it at the proper digit position
                               1555                 :                :      */
 8798                          1556                 :           3823 :     init_var(&arg);
                               1557                 :           3823 :     set_var_from_num(num, &arg);
                               1558                 :                : 
 7695                          1559                 :           3823 :     round_var(&arg, scale);
                               1560                 :                : 
                               1561                 :                :     /* We don't allow negative output dscale */
                               1562         [ +  + ]:           3823 :     if (scale < 0)
                               1563                 :             90 :         arg.dscale = 0;
                               1564                 :                : 
                               1565                 :                :     /*
                               1566                 :                :      * Return the rounded result
                               1567                 :                :      */
 8798                          1568                 :           3823 :     res = make_result(&arg);
                               1569                 :                : 
                               1570                 :           3823 :     free_var(&arg);
 8706                          1571                 :           3823 :     PG_RETURN_NUMERIC(res);
                               1572                 :                : }
                               1573                 :                : 
                               1574                 :                : 
                               1575                 :                : /*
                               1576                 :                :  * numeric_trunc() -
                               1577                 :                :  *
                               1578                 :                :  *  Truncate a value to have 'scale' digits after the decimal point.
                               1579                 :                :  *  We allow negative 'scale', implying a truncation before the decimal
                               1580                 :                :  *  point --- Oracle interprets truncation that way.
                               1581                 :                :  */
                               1582                 :                : Datum
                               1583                 :            289 : numeric_trunc(PG_FUNCTION_ARGS)
                               1584                 :                : {
                               1585                 :            289 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1586                 :            289 :     int32       scale = PG_GETARG_INT32(1);
                               1587                 :                :     Numeric     res;
                               1588                 :                :     NumericVar  arg;
                               1589                 :                : 
                               1590                 :                :     /*
                               1591                 :                :      * Handle NaN and infinities
                               1592                 :                :      */
 1362                          1593         [ +  + ]:            289 :     if (NUMERIC_IS_SPECIAL(num))
                               1594                 :             18 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1595                 :                : 
                               1596                 :                :     /*
                               1597                 :                :      * Limit the scale value to avoid possible overflow in calculations
                               1598                 :                :      */
 7865                          1599                 :            271 :     scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
                               1600                 :            271 :     scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
                               1601                 :                : 
                               1602                 :                :     /*
                               1603                 :                :      * Unpack the argument and truncate it at the proper digit position
                               1604                 :                :      */
 9237 JanWieck@Yahoo.com       1605                 :            271 :     init_var(&arg);
                               1606                 :            271 :     set_var_from_num(num, &arg);
                               1607                 :                : 
 7695 tgl@sss.pgh.pa.us        1608                 :            271 :     trunc_var(&arg, scale);
                               1609                 :                : 
                               1610                 :                :     /* We don't allow negative output dscale */
                               1611         [ -  + ]:            271 :     if (scale < 0)
 7695 tgl@sss.pgh.pa.us        1612                 :UBC           0 :         arg.dscale = 0;
                               1613                 :                : 
                               1614                 :                :     /*
                               1615                 :                :      * Return the truncated result
                               1616                 :                :      */
 9237 JanWieck@Yahoo.com       1617                 :CBC         271 :     res = make_result(&arg);
                               1618                 :                : 
                               1619                 :            271 :     free_var(&arg);
 8706 tgl@sss.pgh.pa.us        1620                 :            271 :     PG_RETURN_NUMERIC(res);
                               1621                 :                : }
                               1622                 :                : 
                               1623                 :                : 
                               1624                 :                : /*
                               1625                 :                :  * numeric_ceil() -
                               1626                 :                :  *
                               1627                 :                :  *  Return the smallest integer greater than or equal to the argument
                               1628                 :                :  */
                               1629                 :                : Datum
 8660                          1630                 :            111 : numeric_ceil(PG_FUNCTION_ARGS)
                               1631                 :                : {
                               1632                 :            111 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1633                 :                :     Numeric     res;
                               1634                 :                :     NumericVar  result;
                               1635                 :                : 
                               1636                 :                :     /*
                               1637                 :                :      * Handle NaN and infinities
                               1638                 :                :      */
 1362                          1639         [ +  + ]:            111 :     if (NUMERIC_IS_SPECIAL(num))
                               1640                 :              9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1641                 :                : 
 4162 heikki.linnakangas@i     1642                 :            102 :     init_var_from_num(num, &result);
 9237 JanWieck@Yahoo.com       1643                 :            102 :     ceil_var(&result, &result);
                               1644                 :                : 
                               1645                 :            102 :     res = make_result(&result);
                               1646                 :            102 :     free_var(&result);
                               1647                 :                : 
 8660 tgl@sss.pgh.pa.us        1648                 :            102 :     PG_RETURN_NUMERIC(res);
                               1649                 :                : }
                               1650                 :                : 
                               1651                 :                : 
                               1652                 :                : /*
                               1653                 :                :  * numeric_floor() -
                               1654                 :                :  *
                               1655                 :                :  *  Return the largest integer equal to or less than the argument
                               1656                 :                :  */
                               1657                 :                : Datum
                               1658                 :             63 : numeric_floor(PG_FUNCTION_ARGS)
                               1659                 :                : {
                               1660                 :             63 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1661                 :                :     Numeric     res;
                               1662                 :                :     NumericVar  result;
                               1663                 :                : 
                               1664                 :                :     /*
                               1665                 :                :      * Handle NaN and infinities
                               1666                 :                :      */
 1362                          1667         [ +  + ]:             63 :     if (NUMERIC_IS_SPECIAL(num))
                               1668                 :              9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1669                 :                : 
 4162 heikki.linnakangas@i     1670                 :             54 :     init_var_from_num(num, &result);
 9237 JanWieck@Yahoo.com       1671                 :             54 :     floor_var(&result, &result);
                               1672                 :                : 
                               1673                 :             54 :     res = make_result(&result);
                               1674                 :             54 :     free_var(&result);
                               1675                 :                : 
 8660 tgl@sss.pgh.pa.us        1676                 :             54 :     PG_RETURN_NUMERIC(res);
                               1677                 :                : }
                               1678                 :                : 
                               1679                 :                : 
                               1680                 :                : /*
                               1681                 :                :  * generate_series_numeric() -
                               1682                 :                :  *
                               1683                 :                :  *  Generate series of numeric.
                               1684                 :                :  */
                               1685                 :                : Datum
 3442 fujii@postgresql.org     1686                 :            108 : generate_series_numeric(PG_FUNCTION_ARGS)
                               1687                 :                : {
                               1688                 :            108 :     return generate_series_step_numeric(fcinfo);
                               1689                 :                : }
                               1690                 :                : 
                               1691                 :                : Datum
                               1692                 :            210 : generate_series_step_numeric(PG_FUNCTION_ARGS)
                               1693                 :                : {
                               1694                 :                :     generate_series_numeric_fctx *fctx;
                               1695                 :                :     FuncCallContext *funcctx;
                               1696                 :                :     MemoryContext oldcontext;
                               1697                 :                : 
                               1698         [ +  + ]:            210 :     if (SRF_IS_FIRSTCALL())
                               1699                 :                :     {
                               1700                 :             69 :         Numeric     start_num = PG_GETARG_NUMERIC(0);
                               1701                 :             69 :         Numeric     stop_num = PG_GETARG_NUMERIC(1);
                               1702                 :             69 :         NumericVar  steploc = const_one;
                               1703                 :                : 
                               1704                 :                :         /* Reject NaN and infinities in start and stop values */
 1362 tgl@sss.pgh.pa.us        1705         [ +  + ]:             69 :         if (NUMERIC_IS_SPECIAL(start_num))
                               1706                 :                :         {
                               1707         [ +  + ]:              6 :             if (NUMERIC_IS_NAN(start_num))
                               1708         [ +  - ]:              3 :                 ereport(ERROR,
                               1709                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1710                 :                :                          errmsg("start value cannot be NaN")));
                               1711                 :                :             else
                               1712         [ +  - ]:              3 :                 ereport(ERROR,
                               1713                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1714                 :                :                          errmsg("start value cannot be infinity")));
                               1715                 :                :         }
                               1716         [ +  + ]:             63 :         if (NUMERIC_IS_SPECIAL(stop_num))
                               1717                 :                :         {
                               1718         [ +  + ]:              6 :             if (NUMERIC_IS_NAN(stop_num))
                               1719         [ +  - ]:              3 :                 ereport(ERROR,
                               1720                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1721                 :                :                          errmsg("stop value cannot be NaN")));
                               1722                 :                :             else
                               1723         [ +  - ]:              3 :                 ereport(ERROR,
                               1724                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1725                 :                :                          errmsg("stop value cannot be infinity")));
                               1726                 :                :         }
                               1727                 :                : 
                               1728                 :                :         /* see if we were given an explicit step size */
 3442 fujii@postgresql.org     1729         [ +  + ]:             57 :         if (PG_NARGS() == 3)
                               1730                 :                :         {
 3340 tgl@sss.pgh.pa.us        1731                 :             27 :             Numeric     step_num = PG_GETARG_NUMERIC(2);
                               1732                 :                : 
 1362                          1733         [ +  + ]:             27 :             if (NUMERIC_IS_SPECIAL(step_num))
                               1734                 :                :             {
                               1735         [ +  + ]:              6 :                 if (NUMERIC_IS_NAN(step_num))
                               1736         [ +  - ]:              3 :                     ereport(ERROR,
                               1737                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1738                 :                :                              errmsg("step size cannot be NaN")));
                               1739                 :                :                 else
                               1740         [ +  - ]:              3 :                     ereport(ERROR,
                               1741                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1742                 :                :                              errmsg("step size cannot be infinity")));
                               1743                 :                :             }
                               1744                 :                : 
 3442 fujii@postgresql.org     1745                 :             21 :             init_var_from_num(step_num, &steploc);
                               1746                 :                : 
                               1747         [ +  + ]:             21 :             if (cmp_var(&steploc, &const_zero) == 0)
                               1748         [ +  - ]:              3 :                 ereport(ERROR,
                               1749                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1750                 :                :                          errmsg("step size cannot equal zero")));
                               1751                 :                :         }
                               1752                 :                : 
                               1753                 :                :         /* create a function context for cross-call persistence */
                               1754                 :             48 :         funcctx = SRF_FIRSTCALL_INIT();
                               1755                 :                : 
                               1756                 :                :         /*
                               1757                 :                :          * Switch to memory context appropriate for multiple function calls.
                               1758                 :                :          */
                               1759                 :             48 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                               1760                 :                : 
                               1761                 :                :         /* allocate memory for user context */
                               1762                 :                :         fctx = (generate_series_numeric_fctx *)
                               1763                 :             48 :             palloc(sizeof(generate_series_numeric_fctx));
                               1764                 :                : 
                               1765                 :                :         /*
                               1766                 :                :          * Use fctx to keep state from call to call. Seed current with the
                               1767                 :                :          * original start value. We must copy the start_num and stop_num
                               1768                 :                :          * values rather than pointing to them, since we may have detoasted
                               1769                 :                :          * them in the per-call context.
                               1770                 :                :          */
 3405                          1771                 :             48 :         init_var(&fctx->current);
                               1772                 :             48 :         init_var(&fctx->stop);
 3442                          1773                 :             48 :         init_var(&fctx->step);
                               1774                 :                : 
 3405                          1775                 :             48 :         set_var_from_num(start_num, &fctx->current);
                               1776                 :             48 :         set_var_from_num(stop_num, &fctx->stop);
 3442                          1777                 :             48 :         set_var_from_var(&steploc, &fctx->step);
                               1778                 :                : 
                               1779                 :             48 :         funcctx->user_fctx = fctx;
                               1780                 :             48 :         MemoryContextSwitchTo(oldcontext);
                               1781                 :                :     }
                               1782                 :                : 
                               1783                 :                :     /* stuff done on every call of the function */
                               1784                 :            189 :     funcctx = SRF_PERCALL_SETUP();
                               1785                 :                : 
                               1786                 :                :     /*
                               1787                 :                :      * Get the saved state and use current state as the result of this
                               1788                 :                :      * iteration.
                               1789                 :                :      */
                               1790                 :            189 :     fctx = funcctx->user_fctx;
                               1791                 :                : 
                               1792   [ +  +  +  + ]:            366 :     if ((fctx->step.sign == NUMERIC_POS &&
                               1793                 :            177 :          cmp_var(&fctx->current, &fctx->stop) <= 0) ||
                               1794   [ +  +  +  + ]:             69 :         (fctx->step.sign == NUMERIC_NEG &&
                               1795                 :             12 :          cmp_var(&fctx->current, &fctx->stop) >= 0))
                               1796                 :                :     {
 3340 tgl@sss.pgh.pa.us        1797                 :            141 :         Numeric     result = make_result(&fctx->current);
                               1798                 :                : 
                               1799                 :                :         /* switch to memory context appropriate for iteration calculation */
 3442 fujii@postgresql.org     1800                 :            141 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                               1801                 :                : 
                               1802                 :                :         /* increment current in preparation for next iteration */
                               1803                 :            141 :         add_var(&fctx->current, &fctx->step, &fctx->current);
                               1804                 :            141 :         MemoryContextSwitchTo(oldcontext);
                               1805                 :                : 
                               1806                 :                :         /* do when there is more left to send */
                               1807                 :            141 :         SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
                               1808                 :                :     }
                               1809                 :                :     else
                               1810                 :                :         /* do when there is no more left */
                               1811                 :             48 :         SRF_RETURN_DONE(funcctx);
                               1812                 :                : }
                               1813                 :                : 
                               1814                 :                : 
                               1815                 :                : /*
                               1816                 :                :  * Implements the numeric version of the width_bucket() function
                               1817                 :                :  * defined by SQL2003. See also width_bucket_float8().
                               1818                 :                :  *
                               1819                 :                :  * 'bound1' and 'bound2' are the lower and upper bounds of the
                               1820                 :                :  * histogram's range, respectively. 'count' is the number of buckets
                               1821                 :                :  * in the histogram. width_bucket() returns an integer indicating the
                               1822                 :                :  * bucket number that 'operand' belongs to in an equiwidth histogram
                               1823                 :                :  * with the specified characteristics. An operand smaller than the
                               1824                 :                :  * lower bound is assigned to bucket 0. An operand greater than the
                               1825                 :                :  * upper bound is assigned to an additional bucket (with number
                               1826                 :                :  * count+1). We don't allow "NaN" for any of the numeric arguments.
                               1827                 :                :  */
                               1828                 :                : Datum
 7275 neilc@samurai.com        1829                 :            390 : width_bucket_numeric(PG_FUNCTION_ARGS)
                               1830                 :                : {
                               1831                 :            390 :     Numeric     operand = PG_GETARG_NUMERIC(0);
                               1832                 :            390 :     Numeric     bound1 = PG_GETARG_NUMERIC(1);
                               1833                 :            390 :     Numeric     bound2 = PG_GETARG_NUMERIC(2);
                               1834                 :            390 :     int32       count = PG_GETARG_INT32(3);
                               1835                 :                :     NumericVar  count_var;
                               1836                 :                :     NumericVar  result_var;
                               1837                 :                :     int32       result;
                               1838                 :                : 
                               1839         [ +  + ]:            390 :     if (count <= 0)
                               1840         [ +  - ]:              6 :         ereport(ERROR,
                               1841                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1842                 :                :                  errmsg("count must be greater than zero")));
                               1843                 :                : 
 1362 tgl@sss.pgh.pa.us        1844         [ +  + ]:            384 :     if (NUMERIC_IS_SPECIAL(operand) ||
                               1845         [ +  + ]:            375 :         NUMERIC_IS_SPECIAL(bound1) ||
                               1846         [ +  + ]:            372 :         NUMERIC_IS_SPECIAL(bound2))
                               1847                 :                :     {
                               1848         [ +  + ]:             18 :         if (NUMERIC_IS_NAN(operand) ||
                               1849         [ +  - ]:             15 :             NUMERIC_IS_NAN(bound1) ||
                               1850         [ -  + ]:             15 :             NUMERIC_IS_NAN(bound2))
                               1851         [ +  - ]:              3 :             ereport(ERROR,
                               1852                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1853                 :                :                      errmsg("operand, lower bound, and upper bound cannot be NaN")));
                               1854                 :                :         /* We allow "operand" to be infinite; cmp_numerics will cope */
 1284                          1855   [ +  +  +  + ]:             15 :         if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
 1362                          1856         [ +  - ]:              9 :             ereport(ERROR,
                               1857                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1858                 :                :                      errmsg("lower and upper bounds must be finite")));
                               1859                 :                :     }
                               1860                 :                : 
 7275 neilc@samurai.com        1861                 :            372 :     init_var(&result_var);
                               1862                 :            372 :     init_var(&count_var);
                               1863                 :                : 
                               1864                 :                :     /* Convert 'count' to a numeric, for ease of use later */
 3313 andres@anarazel.de       1865                 :            372 :     int64_to_numericvar((int64) count, &count_var);
                               1866                 :                : 
 7275 neilc@samurai.com        1867   [ +  +  +  - ]:            372 :     switch (cmp_numerics(bound1, bound2))
                               1868                 :                :     {
                               1869                 :              3 :         case 0:
                               1870         [ +  - ]:              3 :             ereport(ERROR,
                               1871                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1872                 :                :                      errmsg("lower bound cannot equal upper bound")));
                               1873                 :                :             break;
                               1874                 :                : 
                               1875                 :                :             /* bound1 < bound2 */
                               1876                 :            273 :         case -1:
                               1877         [ +  + ]:            273 :             if (cmp_numerics(operand, bound1) < 0)
                               1878                 :             57 :                 set_var_from_var(&const_zero, &result_var);
                               1879         [ +  + ]:            216 :             else if (cmp_numerics(operand, bound2) >= 0)
                               1880                 :             54 :                 add_var(&count_var, &const_one, &result_var);
                               1881                 :                :             else
 1284 tgl@sss.pgh.pa.us        1882                 :            162 :                 compute_bucket(operand, bound1, bound2, &count_var, false,
                               1883                 :                :                                &result_var);
 7275 neilc@samurai.com        1884                 :            273 :             break;
                               1885                 :                : 
                               1886                 :                :             /* bound1 > bound2 */
                               1887                 :             96 :         case 1:
                               1888         [ +  + ]:             96 :             if (cmp_numerics(operand, bound1) > 0)
                               1889                 :              6 :                 set_var_from_var(&const_zero, &result_var);
                               1890         [ +  + ]:             90 :             else if (cmp_numerics(operand, bound2) <= 0)
                               1891                 :             12 :                 add_var(&count_var, &const_one, &result_var);
                               1892                 :                :             else
 1284 tgl@sss.pgh.pa.us        1893                 :             78 :                 compute_bucket(operand, bound1, bound2, &count_var, true,
                               1894                 :                :                                &result_var);
 7275 neilc@samurai.com        1895                 :             96 :             break;
                               1896                 :                :     }
                               1897                 :                : 
                               1898                 :                :     /* if result exceeds the range of a legal int4, we ereport here */
 1856 akorotkov@postgresql     1899         [ -  + ]:            369 :     if (!numericvar_to_int32(&result_var, &result))
 1856 akorotkov@postgresql     1900         [ #  # ]:UBC           0 :         ereport(ERROR,
                               1901                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               1902                 :                :                  errmsg("integer out of range")));
                               1903                 :                : 
 7275 neilc@samurai.com        1904                 :CBC         369 :     free_var(&count_var);
                               1905                 :            369 :     free_var(&result_var);
                               1906                 :                : 
                               1907                 :            369 :     PG_RETURN_INT32(result);
                               1908                 :                : }
                               1909                 :                : 
                               1910                 :                : /*
                               1911                 :                :  * 'operand' is inside the bucket range, so determine the correct
                               1912                 :                :  * bucket for it to go. The calculations performed by this function
                               1913                 :                :  * are derived directly from the SQL2003 spec. Note however that we
                               1914                 :                :  * multiply by count before dividing, to avoid unnecessary roundoff error.
                               1915                 :                :  */
                               1916                 :                : static void
                               1917                 :            240 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
                               1918                 :                :                const NumericVar *count_var, bool reversed_bounds,
                               1919                 :                :                NumericVar *result_var)
                               1920                 :                : {
                               1921                 :                :     NumericVar  bound1_var;
                               1922                 :                :     NumericVar  bound2_var;
                               1923                 :                :     NumericVar  operand_var;
                               1924                 :                : 
 4162 heikki.linnakangas@i     1925                 :            240 :     init_var_from_num(bound1, &bound1_var);
                               1926                 :            240 :     init_var_from_num(bound2, &bound2_var);
                               1927                 :            240 :     init_var_from_num(operand, &operand_var);
                               1928                 :                : 
 1284 tgl@sss.pgh.pa.us        1929         [ +  + ]:            240 :     if (!reversed_bounds)
                               1930                 :                :     {
 7275 neilc@samurai.com        1931                 :            162 :         sub_var(&operand_var, &bound1_var, &operand_var);
                               1932                 :            162 :         sub_var(&bound2_var, &bound1_var, &bound2_var);
                               1933                 :                :     }
                               1934                 :                :     else
                               1935                 :                :     {
                               1936                 :             78 :         sub_var(&bound1_var, &operand_var, &operand_var);
 1284 tgl@sss.pgh.pa.us        1937                 :             78 :         sub_var(&bound1_var, &bound2_var, &bound2_var);
                               1938                 :                :     }
                               1939                 :                : 
                               1940                 :            240 :     mul_var(&operand_var, count_var, &operand_var,
                               1941                 :            240 :             operand_var.dscale + count_var->dscale);
                               1942                 :            240 :     div_var(&operand_var, &bound2_var, result_var,
                               1943                 :                :             select_div_scale(&operand_var, &bound2_var), true);
                               1944                 :                : 
                               1945                 :                :     /*
                               1946                 :                :      * Roundoff in the division could give us a quotient exactly equal to
                               1947                 :                :      * "count", which is too large.  Clamp so that we do not emit a result
                               1948                 :                :      * larger than "count".
                               1949                 :                :      */
  380                          1950         [ +  + ]:            240 :     if (cmp_var(result_var, count_var) >= 0)
                               1951                 :              6 :         set_var_from_var(count_var, result_var);
                               1952                 :                :     else
                               1953                 :                :     {
                               1954                 :            234 :         add_var(result_var, &const_one, result_var);
                               1955                 :            234 :         floor_var(result_var, result_var);
                               1956                 :                :     }
                               1957                 :                : 
 7275 neilc@samurai.com        1958                 :            240 :     free_var(&bound1_var);
                               1959                 :            240 :     free_var(&bound2_var);
                               1960                 :            240 :     free_var(&operand_var);
 7168 bruce@momjian.us         1961                 :            240 : }
                               1962                 :                : 
                               1963                 :                : /* ----------------------------------------------------------------------
                               1964                 :                :  *
                               1965                 :                :  * Comparison functions
                               1966                 :                :  *
                               1967                 :                :  * Note: btree indexes need these routines not to leak memory; therefore,
                               1968                 :                :  * be careful to free working copies of toasted datums.  Most places don't
                               1969                 :                :  * need to be so careful.
                               1970                 :                :  *
                               1971                 :                :  * Sort support:
                               1972                 :                :  *
                               1973                 :                :  * We implement the sortsupport strategy routine in order to get the benefit of
                               1974                 :                :  * abbreviation. The ordinary numeric comparison can be quite slow as a result
                               1975                 :                :  * of palloc/pfree cycles (due to detoasting packed values for alignment);
                               1976                 :                :  * while this could be worked on itself, the abbreviation strategy gives more
                               1977                 :                :  * speedup in many common cases.
                               1978                 :                :  *
                               1979                 :                :  * Two different representations are used for the abbreviated form, one in
                               1980                 :                :  * int32 and one in int64, whichever fits into a by-value Datum.  In both cases
                               1981                 :                :  * the representation is negated relative to the original value, because we use
                               1982                 :                :  * the largest negative value for NaN, which sorts higher than other values. We
                               1983                 :                :  * convert the absolute value of the numeric to a 31-bit or 63-bit positive
                               1984                 :                :  * value, and then negate it if the original number was positive.
                               1985                 :                :  *
                               1986                 :                :  * We abort the abbreviation process if the abbreviation cardinality is below
                               1987                 :                :  * 0.01% of the row count (1 per 10k non-null rows).  The actual break-even
                               1988                 :                :  * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
                               1989                 :                :  * very small penalty), but we don't want to build up too many abbreviated
                               1990                 :                :  * values before first testing for abort, so we take the slightly pessimistic
                               1991                 :                :  * number.  We make no attempt to estimate the cardinality of the real values,
                               1992                 :                :  * since it plays no part in the cost model here (if the abbreviation is equal,
                               1993                 :                :  * the cost of comparing equal and unequal underlying values is comparable).
                               1994                 :                :  * We discontinue even checking for abort (saving us the hashing overhead) if
                               1995                 :                :  * the estimated cardinality gets to 100k; that would be enough to support many
                               1996                 :                :  * billions of rows while doing no worse than breaking even.
                               1997                 :                :  *
                               1998                 :                :  * ----------------------------------------------------------------------
                               1999                 :                :  */
                               2000                 :                : 
                               2001                 :                : /*
                               2002                 :                :  * Sort support strategy routine.
                               2003                 :                :  */
                               2004                 :                : Datum
 3300 rhaas@postgresql.org     2005                 :            505 : numeric_sortsupport(PG_FUNCTION_ARGS)
                               2006                 :                : {
                               2007                 :            505 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
                               2008                 :                : 
                               2009                 :            505 :     ssup->comparator = numeric_fast_cmp;
                               2010                 :                : 
                               2011         [ +  + ]:            505 :     if (ssup->abbreviate)
                               2012                 :                :     {
                               2013                 :                :         NumericSortSupport *nss;
                               2014                 :            123 :         MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
                               2015                 :                : 
                               2016                 :            123 :         nss = palloc(sizeof(NumericSortSupport));
                               2017                 :                : 
                               2018                 :                :         /*
                               2019                 :                :          * palloc a buffer for handling unaligned packed values in addition to
                               2020                 :                :          * the support struct
                               2021                 :                :          */
                               2022                 :            123 :         nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
                               2023                 :                : 
                               2024                 :            123 :         nss->input_count = 0;
                               2025                 :            123 :         nss->estimating = true;
                               2026                 :            123 :         initHyperLogLog(&nss->abbr_card, 10);
                               2027                 :                : 
                               2028                 :            123 :         ssup->ssup_extra = nss;
                               2029                 :                : 
                               2030                 :            123 :         ssup->abbrev_full_comparator = ssup->comparator;
                               2031                 :            123 :         ssup->comparator = numeric_cmp_abbrev;
                               2032                 :            123 :         ssup->abbrev_converter = numeric_abbrev_convert;
                               2033                 :            123 :         ssup->abbrev_abort = numeric_abbrev_abort;
                               2034                 :                : 
                               2035                 :            123 :         MemoryContextSwitchTo(oldcontext);
                               2036                 :                :     }
                               2037                 :                : 
                               2038                 :            505 :     PG_RETURN_VOID();
                               2039                 :                : }
                               2040                 :                : 
                               2041                 :                : /*
                               2042                 :                :  * Abbreviate a numeric datum, handling NaNs and detoasting
                               2043                 :                :  * (must not leak memory!)
                               2044                 :                :  */
                               2045                 :                : static Datum
                               2046                 :           9566 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
                               2047                 :                : {
                               2048                 :           9566 :     NumericSortSupport *nss = ssup->ssup_extra;
                               2049                 :           9566 :     void       *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
                               2050                 :                :     Numeric     value;
                               2051                 :                :     Datum       result;
                               2052                 :                : 
                               2053                 :           9566 :     nss->input_count += 1;
                               2054                 :                : 
                               2055                 :                :     /*
                               2056                 :                :      * This is to handle packed datums without needing a palloc/pfree cycle;
                               2057                 :                :      * we keep and reuse a buffer large enough to handle any short datum.
                               2058                 :                :      */
                               2059         [ +  + ]:           9566 :     if (VARATT_IS_SHORT(original_varatt))
                               2060                 :                :     {
                               2061                 :            513 :         void       *buf = nss->buf;
                               2062                 :            513 :         Size        sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
                               2063                 :                : 
                               2064         [ -  + ]:            513 :         Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
                               2065                 :                : 
                               2066                 :            513 :         SET_VARSIZE(buf, VARHDRSZ + sz);
                               2067                 :            513 :         memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
                               2068                 :                : 
                               2069                 :            513 :         value = (Numeric) buf;
                               2070                 :                :     }
                               2071                 :                :     else
                               2072                 :           9053 :         value = (Numeric) original_varatt;
                               2073                 :                : 
 1362 tgl@sss.pgh.pa.us        2074         [ +  + ]:           9566 :     if (NUMERIC_IS_SPECIAL(value))
                               2075                 :                :     {
                               2076         [ +  + ]:             75 :         if (NUMERIC_IS_PINF(value))
                               2077                 :             24 :             result = NUMERIC_ABBREV_PINF;
                               2078         [ +  + ]:             51 :         else if (NUMERIC_IS_NINF(value))
                               2079                 :             24 :             result = NUMERIC_ABBREV_NINF;
                               2080                 :                :         else
                               2081                 :             27 :             result = NUMERIC_ABBREV_NAN;
                               2082                 :                :     }
                               2083                 :                :     else
                               2084                 :                :     {
                               2085                 :                :         NumericVar  var;
                               2086                 :                : 
 3300 rhaas@postgresql.org     2087                 :           9491 :         init_var_from_num(value, &var);
                               2088                 :                : 
                               2089                 :           9491 :         result = numeric_abbrev_convert_var(&var, nss);
                               2090                 :                :     }
                               2091                 :                : 
                               2092                 :                :     /* should happen only for external/compressed toasts */
                               2093         [ -  + ]:           9566 :     if ((Pointer) original_varatt != DatumGetPointer(original_datum))
 3300 rhaas@postgresql.org     2094                 :UBC           0 :         pfree(original_varatt);
                               2095                 :                : 
 3300 rhaas@postgresql.org     2096                 :CBC        9566 :     return result;
                               2097                 :                : }
                               2098                 :                : 
                               2099                 :                : /*
                               2100                 :                :  * Consider whether to abort abbreviation.
                               2101                 :                :  *
                               2102                 :                :  * We pay no attention to the cardinality of the non-abbreviated data. There is
                               2103                 :                :  * no reason to do so: unlike text, we have no fast check for equal values, so
                               2104                 :                :  * we pay the full overhead whenever the abbreviations are equal regardless of
                               2105                 :                :  * whether the underlying values are also equal.
                               2106                 :                :  */
                               2107                 :                : static bool
                               2108                 :             72 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
                               2109                 :                : {
                               2110                 :             72 :     NumericSortSupport *nss = ssup->ssup_extra;
                               2111                 :                :     double      abbr_card;
                               2112                 :                : 
                               2113   [ -  +  -  -  :             72 :     if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
                                              -  - ]
                               2114                 :             72 :         return false;
                               2115                 :                : 
 3300 rhaas@postgresql.org     2116                 :UBC           0 :     abbr_card = estimateHyperLogLog(&nss->abbr_card);
                               2117                 :                : 
                               2118                 :                :     /*
                               2119                 :                :      * If we have >100k distinct values, then even if we were sorting many
                               2120                 :                :      * billion rows we'd likely still break even, and the penalty of undoing
                               2121                 :                :      * that many rows of abbrevs would probably not be worth it. Stop even
                               2122                 :                :      * counting at that point.
                               2123                 :                :      */
                               2124         [ #  # ]:              0 :     if (abbr_card > 100000.0)
                               2125                 :                :     {
                               2126                 :                : #ifdef TRACE_SORT
                               2127         [ #  # ]:              0 :         if (trace_sort)
                               2128         [ #  # ]:              0 :             elog(LOG,
                               2129                 :                :                  "numeric_abbrev: estimation ends at cardinality %f"
                               2130                 :                :                  " after " INT64_FORMAT " values (%d rows)",
                               2131                 :                :                  abbr_card, nss->input_count, memtupcount);
                               2132                 :                : #endif
                               2133                 :              0 :         nss->estimating = false;
                               2134                 :              0 :         return false;
                               2135                 :                :     }
                               2136                 :                : 
                               2137                 :                :     /*
                               2138                 :                :      * Target minimum cardinality is 1 per ~10k of non-null inputs.  (The
                               2139                 :                :      * break even point is somewhere between one per 100k rows, where
                               2140                 :                :      * abbreviation has a very slight penalty, and 1 per 10k where it wins by
                               2141                 :                :      * a measurable percentage.)  We use the relatively pessimistic 10k
                               2142                 :                :      * threshold, and add a 0.5 row fudge factor, because it allows us to
                               2143                 :                :      * abort earlier on genuinely pathological data where we've had exactly
                               2144                 :                :      * one abbreviated value in the first 10k (non-null) rows.
                               2145                 :                :      */
                               2146         [ #  # ]:              0 :     if (abbr_card < nss->input_count / 10000.0 + 0.5)
                               2147                 :                :     {
                               2148                 :                : #ifdef TRACE_SORT
                               2149         [ #  # ]:              0 :         if (trace_sort)
                               2150         [ #  # ]:              0 :             elog(LOG,
                               2151                 :                :                  "numeric_abbrev: aborting abbreviation at cardinality %f"
                               2152                 :                :                  " below threshold %f after " INT64_FORMAT " values (%d rows)",
                               2153                 :                :                  abbr_card, nss->input_count / 10000.0 + 0.5,
                               2154                 :                :                  nss->input_count, memtupcount);
                               2155                 :                : #endif
                               2156                 :              0 :         return true;
                               2157                 :                :     }
                               2158                 :                : 
                               2159                 :                : #ifdef TRACE_SORT
                               2160         [ #  # ]:              0 :     if (trace_sort)
                               2161         [ #  # ]:              0 :         elog(LOG,
                               2162                 :                :              "numeric_abbrev: cardinality %f"
                               2163                 :                :              " after " INT64_FORMAT " values (%d rows)",
                               2164                 :                :              abbr_card, nss->input_count, memtupcount);
                               2165                 :                : #endif
                               2166                 :                : 
                               2167                 :              0 :     return false;
                               2168                 :                : }
                               2169                 :                : 
                               2170                 :                : /*
                               2171                 :                :  * Non-fmgr interface to the comparison routine to allow sortsupport to elide
                               2172                 :                :  * the fmgr call.  The saving here is small given how slow numeric comparisons
                               2173                 :                :  * are, but it is a required part of the sort support API when abbreviations
                               2174                 :                :  * are performed.
                               2175                 :                :  *
                               2176                 :                :  * Two palloc/pfree cycles could be saved here by using persistent buffers for
                               2177                 :                :  * aligning short-varlena inputs, but this has not so far been considered to
                               2178                 :                :  * be worth the effort.
                               2179                 :                :  */
                               2180                 :                : static int
 3300 rhaas@postgresql.org     2181                 :CBC     2356553 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
                               2182                 :                : {
                               2183                 :        2356553 :     Numeric     nx = DatumGetNumeric(x);
                               2184                 :        2356553 :     Numeric     ny = DatumGetNumeric(y);
                               2185                 :                :     int         result;
                               2186                 :                : 
                               2187                 :        2356553 :     result = cmp_numerics(nx, ny);
                               2188                 :                : 
                               2189         [ +  + ]:        2356553 :     if ((Pointer) nx != DatumGetPointer(x))
                               2190                 :          86415 :         pfree(nx);
                               2191         [ +  + ]:        2356553 :     if ((Pointer) ny != DatumGetPointer(y))
                               2192                 :          86412 :         pfree(ny);
                               2193                 :                : 
                               2194                 :        2356553 :     return result;
                               2195                 :                : }
                               2196                 :                : 
                               2197                 :                : /*
                               2198                 :                :  * Compare abbreviations of values. (Abbreviations may be equal where the true
                               2199                 :                :  * values differ, but if the abbreviations differ, they must reflect the
                               2200                 :                :  * ordering of the true values.)
                               2201                 :                :  */
                               2202                 :                : static int
                               2203                 :          94507 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
                               2204                 :                : {
                               2205                 :                :     /*
                               2206                 :                :      * NOTE WELL: this is intentionally backwards, because the abbreviation is
                               2207                 :                :      * negated relative to the original value, to handle NaN/infinity cases.
                               2208                 :                :      */
                               2209         [ +  + ]:          94507 :     if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
                               2210                 :          49283 :         return 1;
                               2211         [ +  + ]:          45224 :     if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
                               2212                 :          45114 :         return -1;
                               2213                 :            110 :     return 0;
                               2214                 :                : }
                               2215                 :                : 
                               2216                 :                : /*
                               2217                 :                :  * Abbreviate a NumericVar according to the available bit size.
                               2218                 :                :  *
                               2219                 :                :  * The 31-bit value is constructed as:
                               2220                 :                :  *
                               2221                 :                :  *  0 + 7bits digit weight + 24 bits digit value
                               2222                 :                :  *
                               2223                 :                :  * where the digit weight is in single decimal digits, not digit words, and
                               2224                 :                :  * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
                               2225                 :                :  * significant decimal digits of the value converted to binary. Values whose
                               2226                 :                :  * weights would fall outside the representable range are rounded off to zero
                               2227                 :                :  * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
                               2228                 :                :  * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
                               2229                 :                :  * where values are outside the range 10^-44 to 10^83, which is not considered
                               2230                 :                :  * to be a serious limitation, or when values are of the same magnitude and
                               2231                 :                :  * equal in the first 7 decimal digits, which is considered to be an
                               2232                 :                :  * unavoidable limitation given the available bits. (Stealing three more bits
                               2233                 :                :  * to compare another digit would narrow the range of representable weights by
                               2234                 :                :  * a factor of 8, which starts to look like a real limiting factor.)
                               2235                 :                :  *
                               2236                 :                :  * (The value 44 for the excess is essentially arbitrary)
                               2237                 :                :  *
                               2238                 :                :  * The 63-bit value is constructed as:
                               2239                 :                :  *
                               2240                 :                :  *  0 + 7bits weight + 4 x 14-bit packed digit words
                               2241                 :                :  *
                               2242                 :                :  * The weight in this case is again stored in excess-44, but this time it is
                               2243                 :                :  * the original weight in digit words (i.e. powers of 10000). The first four
                               2244                 :                :  * digit words of the value (if present; trailing zeros are assumed as needed)
                               2245                 :                :  * are packed into 14 bits each to form the rest of the value. Again,
                               2246                 :                :  * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
                               2247                 :                :  * representable range in this case is 10^-176 to 10^332, which is considered
                               2248                 :                :  * to be good enough for all practical purposes, and comparison of 4 words
                               2249                 :                :  * means that at least 13 decimal digits are compared, which is considered to
                               2250                 :                :  * be a reasonable compromise between effectiveness and efficiency in computing
                               2251                 :                :  * the abbreviation.
                               2252                 :                :  *
                               2253                 :                :  * (The value 44 for the excess is even more arbitrary here, it was chosen just
                               2254                 :                :  * to match the value used in the 31-bit case)
                               2255                 :                :  *
                               2256                 :                :  * [1] - Excess-k representation means that the value is offset by adding 'k'
                               2257                 :                :  * and then treated as unsigned, so the smallest representable value is stored
                               2258                 :                :  * with all bits zero. This allows simple comparisons to work on the composite
                               2259                 :                :  * value.
                               2260                 :                :  */
                               2261                 :                : 
                               2262                 :                : #if NUMERIC_ABBREV_BITS == 64
                               2263                 :                : 
                               2264                 :                : static Datum
 2408 andres@anarazel.de       2265                 :           9491 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
                               2266                 :                : {
 3300 rhaas@postgresql.org     2267                 :           9491 :     int         ndigits = var->ndigits;
                               2268                 :           9491 :     int         weight = var->weight;
                               2269                 :                :     int64       result;
                               2270                 :                : 
                               2271   [ +  +  -  + ]:           9491 :     if (ndigits == 0 || weight < -44)
                               2272                 :                :     {
                               2273                 :             26 :         result = 0;
                               2274                 :                :     }
                               2275         [ +  + ]:           9465 :     else if (weight > 83)
                               2276                 :                :     {
                               2277                 :              6 :         result = PG_INT64_MAX;
                               2278                 :                :     }
                               2279                 :                :     else
                               2280                 :                :     {
                               2281                 :           9459 :         result = ((int64) (weight + 44) << 56);
                               2282                 :                : 
                               2283   [ -  +  +  + ]:           9459 :         switch (ndigits)
                               2284                 :                :         {
 3300 rhaas@postgresql.org     2285                 :UBC           0 :             default:
                               2286                 :              0 :                 result |= ((int64) var->digits[3]);
                               2287                 :                :                 /* FALLTHROUGH */
 3300 rhaas@postgresql.org     2288                 :CBC        3104 :             case 3:
                               2289                 :           3104 :                 result |= ((int64) var->digits[2]) << 14;
                               2290                 :                :                 /* FALLTHROUGH */
                               2291                 :           9132 :             case 2:
                               2292                 :           9132 :                 result |= ((int64) var->digits[1]) << 28;
                               2293                 :                :                 /* FALLTHROUGH */
                               2294                 :           9459 :             case 1:
                               2295                 :           9459 :                 result |= ((int64) var->digits[0]) << 42;
                               2296                 :           9459 :                 break;
                               2297                 :                :         }
                               2298                 :                :     }
                               2299                 :                : 
                               2300                 :                :     /* the abbrev is negated relative to the original */
                               2301         [ +  + ]:           9491 :     if (var->sign == NUMERIC_POS)
                               2302                 :           9442 :         result = -result;
                               2303                 :                : 
                               2304         [ +  - ]:           9491 :     if (nss->estimating)
                               2305                 :                :     {
                               2306                 :           9491 :         uint32      tmp = ((uint32) result
                               2307                 :           9491 :                            ^ (uint32) ((uint64) result >> 32));
                               2308                 :                : 
                               2309                 :           9491 :         addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
                               2310                 :                :     }
                               2311                 :                : 
 3299                          2312                 :           9491 :     return NumericAbbrevGetDatum(result);
                               2313                 :                : }
                               2314                 :                : 
                               2315                 :                : #endif                          /* NUMERIC_ABBREV_BITS == 64 */
                               2316                 :                : 
                               2317                 :                : #if NUMERIC_ABBREV_BITS == 32
                               2318                 :                : 
                               2319                 :                : static Datum
                               2320                 :                : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
                               2321                 :                : {
                               2322                 :                :     int         ndigits = var->ndigits;
                               2323                 :                :     int         weight = var->weight;
                               2324                 :                :     int32       result;
                               2325                 :                : 
                               2326                 :                :     if (ndigits == 0 || weight < -11)
                               2327                 :                :     {
                               2328                 :                :         result = 0;
                               2329                 :                :     }
                               2330                 :                :     else if (weight > 20)
                               2331                 :                :     {
                               2332                 :                :         result = PG_INT32_MAX;
                               2333                 :                :     }
                               2334                 :                :     else
                               2335                 :                :     {
                               2336                 :                :         NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
                               2337                 :                : 
                               2338                 :                :         weight = (weight + 11) * 4;
                               2339                 :                : 
                               2340                 :                :         result = var->digits[0];
                               2341                 :                : 
                               2342                 :                :         /*
                               2343                 :                :          * "result" now has 1 to 4 nonzero decimal digits. We pack in more
                               2344                 :                :          * digits to make 7 in total (largest we can fit in 24 bits)
                               2345                 :                :          */
                               2346                 :                : 
                               2347                 :                :         if (result > 999)
                               2348                 :                :         {
                               2349                 :                :             /* already have 4 digits, add 3 more */
                               2350                 :                :             result = (result * 1000) + (nxt1 / 10);
                               2351                 :                :             weight += 3;
                               2352                 :                :         }
                               2353                 :                :         else if (result > 99)
                               2354                 :                :         {
                               2355                 :                :             /* already have 3 digits, add 4 more */
                               2356                 :                :             result = (result * 10000) + nxt1;
                               2357                 :                :             weight += 2;
                               2358                 :                :         }
                               2359                 :                :         else if (result > 9)
                               2360                 :                :         {
                               2361                 :                :             NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
                               2362                 :                : 
                               2363                 :                :             /* already have 2 digits, add 5 more */
                               2364                 :                :             result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
                               2365                 :                :             weight += 1;
                               2366                 :                :         }
                               2367                 :                :         else
                               2368                 :                :         {
                               2369                 :                :             NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
                               2370                 :                : 
                               2371                 :                :             /* already have 1 digit, add 6 more */
                               2372                 :                :             result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
                               2373                 :                :         }
                               2374                 :                : 
                               2375                 :                :         result = result | (weight << 24);
                               2376                 :                :     }
                               2377                 :                : 
                               2378                 :                :     /* the abbrev is negated relative to the original */
                               2379                 :                :     if (var->sign == NUMERIC_POS)
                               2380                 :                :         result = -result;
                               2381                 :                : 
                               2382                 :                :     if (nss->estimating)
                               2383                 :                :     {
                               2384                 :                :         uint32      tmp = (uint32) result;
                               2385                 :                : 
                               2386                 :                :         addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
                               2387                 :                :     }
                               2388                 :                : 
                               2389                 :                :     return NumericAbbrevGetDatum(result);
                               2390                 :                : }
                               2391                 :                : 
                               2392                 :                : #endif                          /* NUMERIC_ABBREV_BITS == 32 */
                               2393                 :                : 
                               2394                 :                : /*
                               2395                 :                :  * Ordinary (non-sortsupport) comparisons follow.
                               2396                 :                :  */
                               2397                 :                : 
                               2398                 :                : Datum
 8660 tgl@sss.pgh.pa.us        2399                 :         471315 : numeric_cmp(PG_FUNCTION_ARGS)
                               2400                 :                : {
                               2401                 :         471315 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2402                 :         471315 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2403                 :                :     int         result;
                               2404                 :                : 
 8382                          2405                 :         471315 :     result = cmp_numerics(num1, num2);
                               2406                 :                : 
 8660                          2407         [ +  + ]:         471315 :     PG_FREE_IF_COPY(num1, 0);
                               2408         [ +  + ]:         471315 :     PG_FREE_IF_COPY(num2, 1);
                               2409                 :                : 
                               2410                 :         471315 :     PG_RETURN_INT32(result);
                               2411                 :                : }
                               2412                 :                : 
                               2413                 :                : 
                               2414                 :                : Datum
                               2415                 :         328908 : numeric_eq(PG_FUNCTION_ARGS)
                               2416                 :                : {
                               2417                 :         328908 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2418                 :         328908 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2419                 :                :     bool        result;
                               2420                 :                : 
 8382                          2421                 :         328908 :     result = cmp_numerics(num1, num2) == 0;
                               2422                 :                : 
 8660                          2423         [ +  + ]:         328908 :     PG_FREE_IF_COPY(num1, 0);
                               2424         [ +  + ]:         328908 :     PG_FREE_IF_COPY(num2, 1);
                               2425                 :                : 
                               2426                 :         328908 :     PG_RETURN_BOOL(result);
                               2427                 :                : }
                               2428                 :                : 
                               2429                 :                : Datum
                               2430                 :           2688 : numeric_ne(PG_FUNCTION_ARGS)
                               2431                 :                : {
                               2432                 :           2688 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2433                 :           2688 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2434                 :                :     bool        result;
                               2435                 :                : 
 8382                          2436                 :           2688 :     result = cmp_numerics(num1, num2) != 0;
                               2437                 :                : 
 8660                          2438         [ +  + ]:           2688 :     PG_FREE_IF_COPY(num1, 0);
                               2439         [ +  + ]:           2688 :     PG_FREE_IF_COPY(num2, 1);
                               2440                 :                : 
                               2441                 :           2688 :     PG_RETURN_BOOL(result);
                               2442                 :                : }
                               2443                 :                : 
                               2444                 :                : Datum
                               2445                 :          30798 : numeric_gt(PG_FUNCTION_ARGS)
                               2446                 :                : {
                               2447                 :          30798 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2448                 :          30798 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2449                 :                :     bool        result;
                               2450                 :                : 
 8382                          2451                 :          30798 :     result = cmp_numerics(num1, num2) > 0;
                               2452                 :                : 
 8660                          2453         [ +  + ]:          30798 :     PG_FREE_IF_COPY(num1, 0);
                               2454         [ +  + ]:          30798 :     PG_FREE_IF_COPY(num2, 1);
                               2455                 :                : 
                               2456                 :          30798 :     PG_RETURN_BOOL(result);
                               2457                 :                : }
                               2458                 :                : 
                               2459                 :                : Datum
                               2460                 :           8391 : numeric_ge(PG_FUNCTION_ARGS)
                               2461                 :                : {
                               2462                 :           8391 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2463                 :           8391 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2464                 :                :     bool        result;
                               2465                 :                : 
 8382                          2466                 :           8391 :     result = cmp_numerics(num1, num2) >= 0;
                               2467                 :                : 
 8660                          2468         [ +  + ]:           8391 :     PG_FREE_IF_COPY(num1, 0);
                               2469         [ -  + ]:           8391 :     PG_FREE_IF_COPY(num2, 1);
                               2470                 :                : 
                               2471                 :           8391 :     PG_RETURN_BOOL(result);
                               2472                 :                : }
                               2473                 :                : 
                               2474                 :                : Datum
                               2475                 :          65098 : numeric_lt(PG_FUNCTION_ARGS)
                               2476                 :                : {
                               2477                 :          65098 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2478                 :          65098 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2479                 :                :     bool        result;
                               2480                 :                : 
 8382                          2481                 :          65098 :     result = cmp_numerics(num1, num2) < 0;
                               2482                 :                : 
 8660                          2483         [ +  + ]:          65098 :     PG_FREE_IF_COPY(num1, 0);
                               2484         [ +  + ]:          65098 :     PG_FREE_IF_COPY(num2, 1);
                               2485                 :                : 
                               2486                 :          65098 :     PG_RETURN_BOOL(result);
                               2487                 :                : }
                               2488                 :                : 
                               2489                 :                : Datum
                               2490                 :           8156 : numeric_le(PG_FUNCTION_ARGS)
                               2491                 :                : {
                               2492                 :           8156 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2493                 :           8156 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2494                 :                :     bool        result;
                               2495                 :                : 
 8382                          2496                 :           8156 :     result = cmp_numerics(num1, num2) <= 0;
                               2497                 :                : 
                               2498         [ +  + ]:           8156 :     PG_FREE_IF_COPY(num1, 0);
                               2499         [ +  + ]:           8156 :     PG_FREE_IF_COPY(num2, 1);
                               2500                 :                : 
                               2501                 :           8156 :     PG_RETURN_BOOL(result);
                               2502                 :                : }
                               2503                 :                : 
                               2504                 :                : static int
                               2505                 :        3282668 : cmp_numerics(Numeric num1, Numeric num2)
                               2506                 :                : {
                               2507                 :                :     int         result;
                               2508                 :                : 
                               2509                 :                :     /*
                               2510                 :                :      * We consider all NANs to be equal and larger than any non-NAN (including
                               2511                 :                :      * Infinity).  This is somewhat arbitrary; the important thing is to have
                               2512                 :                :      * a consistent sort order.
                               2513                 :                :      */
 1362                          2514         [ +  + ]:        3282668 :     if (NUMERIC_IS_SPECIAL(num1))
                               2515                 :                :     {
                               2516         [ +  + ]:           4375 :         if (NUMERIC_IS_NAN(num1))
                               2517                 :                :         {
                               2518         [ +  + ]:           4330 :             if (NUMERIC_IS_NAN(num2))
                               2519                 :            714 :                 result = 0;     /* NAN = NAN */
                               2520                 :                :             else
                               2521                 :           3616 :                 result = 1;     /* NAN > non-NAN */
                               2522                 :                :         }
                               2523         [ +  + ]:             45 :         else if (NUMERIC_IS_PINF(num1))
                               2524                 :                :         {
                               2525         [ -  + ]:             36 :             if (NUMERIC_IS_NAN(num2))
 1362 tgl@sss.pgh.pa.us        2526                 :UBC           0 :                 result = -1;    /* PINF < NAN */
 1362 tgl@sss.pgh.pa.us        2527         [ +  + ]:CBC          36 :             else if (NUMERIC_IS_PINF(num2))
                               2528                 :              3 :                 result = 0;     /* PINF = PINF */
                               2529                 :                :             else
                               2530                 :             33 :                 result = 1;     /* PINF > anything else */
                               2531                 :                :         }
                               2532                 :                :         else                    /* num1 must be NINF */
                               2533                 :                :         {
                               2534         [ +  + ]:              9 :             if (NUMERIC_IS_NINF(num2))
                               2535                 :              3 :                 result = 0;     /* NINF = NINF */
                               2536                 :                :             else
                               2537                 :              6 :                 result = -1;    /* NINF < anything else */
                               2538                 :                :         }
                               2539                 :                :     }
                               2540         [ +  + ]:        3278293 :     else if (NUMERIC_IS_SPECIAL(num2))
                               2541                 :                :     {
                               2542         [ +  + ]:           5662 :         if (NUMERIC_IS_NINF(num2))
                               2543                 :              6 :             result = 1;         /* normal > NINF */
                               2544                 :                :         else
                               2545                 :           5656 :             result = -1;        /* normal < NAN or PINF */
                               2546                 :                :     }
                               2547                 :                :     else
                               2548                 :                :     {
 6641 bruce@momjian.us         2549   [ +  +  +  + ]:        6545833 :         result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
 5003 rhaas@postgresql.org     2550   [ +  +  -  +  :        3272776 :                                 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
                                        +  +  +  + ]
 6641 bruce@momjian.us         2551   [ +  +  +  + ]:        3272631 :                                 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
 5003 rhaas@postgresql.org     2552   [ +  +  -  +  :        3273057 :                                 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
                                        +  +  +  + ]
                               2553                 :                :     }
                               2554                 :                : 
 8382 tgl@sss.pgh.pa.us        2555                 :        3282668 :     return result;
                               2556                 :                : }
                               2557                 :                : 
                               2558                 :                : /*
                               2559                 :                :  * in_range support function for numeric.
                               2560                 :                :  */
                               2561                 :                : Datum
 2241                          2562                 :            576 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
                               2563                 :                : {
                               2564                 :            576 :     Numeric     val = PG_GETARG_NUMERIC(0);
                               2565                 :            576 :     Numeric     base = PG_GETARG_NUMERIC(1);
                               2566                 :            576 :     Numeric     offset = PG_GETARG_NUMERIC(2);
                               2567                 :            576 :     bool        sub = PG_GETARG_BOOL(3);
                               2568                 :            576 :     bool        less = PG_GETARG_BOOL(4);
                               2569                 :                :     bool        result;
                               2570                 :                : 
                               2571                 :                :     /*
                               2572                 :                :      * Reject negative (including -Inf) or NaN offset.  Negative is per spec,
                               2573                 :                :      * and NaN is because appropriate semantics for that seem non-obvious.
                               2574                 :                :      */
 1362                          2575         [ +  + ]:            576 :     if (NUMERIC_IS_NAN(offset) ||
                               2576         [ +  - ]:            573 :         NUMERIC_IS_NINF(offset) ||
                               2577   [ +  +  -  +  :            573 :         NUMERIC_SIGN(offset) == NUMERIC_NEG)
                                     +  -  -  +  -  
                                                 - ]
 2241                          2578         [ +  - ]:              3 :         ereport(ERROR,
                               2579                 :                :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
                               2580                 :                :                  errmsg("invalid preceding or following size in window function")));
                               2581                 :                : 
                               2582                 :                :     /*
                               2583                 :                :      * Deal with cases where val and/or base is NaN, following the rule that
                               2584                 :                :      * NaN sorts after non-NaN (cf cmp_numerics).  The offset cannot affect
                               2585                 :                :      * the conclusion.
                               2586                 :                :      */
                               2587         [ +  + ]:            573 :     if (NUMERIC_IS_NAN(val))
                               2588                 :                :     {
                               2589         [ +  + ]:             93 :         if (NUMERIC_IS_NAN(base))
                               2590                 :             30 :             result = true;      /* NAN = NAN */
                               2591                 :                :         else
                               2592                 :             63 :             result = !less;     /* NAN > non-NAN */
                               2593                 :                :     }
                               2594         [ +  + ]:            480 :     else if (NUMERIC_IS_NAN(base))
                               2595                 :                :     {
                               2596                 :             63 :         result = less;          /* non-NAN < NAN */
                               2597                 :                :     }
                               2598                 :                : 
                               2599                 :                :     /*
                               2600                 :                :      * Deal with infinite offset (necessarily +Inf, at this point).
                               2601                 :                :      */
 1362                          2602         [ +  + ]:            417 :     else if (NUMERIC_IS_SPECIAL(offset))
                               2603                 :                :     {
                               2604         [ -  + ]:            210 :         Assert(NUMERIC_IS_PINF(offset));
                               2605   [ +  +  +  + ]:            210 :         if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
                               2606                 :                :         {
                               2607                 :                :             /*
                               2608                 :                :              * base +/- offset would produce NaN, so return true for any val
                               2609                 :                :              * (see in_range_float8_float8() for reasoning).
                               2610                 :                :              */
                               2611                 :             87 :             result = true;
                               2612                 :                :         }
                               2613         [ +  + ]:            123 :         else if (sub)
                               2614                 :                :         {
                               2615                 :                :             /* base - offset must be -inf */
                               2616         [ +  + ]:             75 :             if (less)
                               2617                 :             27 :                 result = NUMERIC_IS_NINF(val);  /* only -inf is <= sum */
                               2618                 :                :             else
                               2619                 :             48 :                 result = true;  /* any val is >= sum */
                               2620                 :                :         }
                               2621                 :                :         else
                               2622                 :                :         {
                               2623                 :                :             /* base + offset must be +inf */
                               2624         [ -  + ]:             48 :             if (less)
 1362 tgl@sss.pgh.pa.us        2625                 :UBC           0 :                 result = true;  /* any val is <= sum */
                               2626                 :                :             else
 1362 tgl@sss.pgh.pa.us        2627                 :CBC          48 :                 result = NUMERIC_IS_PINF(val);  /* only +inf is >= sum */
                               2628                 :                :         }
                               2629                 :                :     }
                               2630                 :                : 
                               2631                 :                :     /*
                               2632                 :                :      * Deal with cases where val and/or base is infinite.  The offset, being
                               2633                 :                :      * now known finite, cannot affect the conclusion.
                               2634                 :                :      */
                               2635         [ +  + ]:            207 :     else if (NUMERIC_IS_SPECIAL(val))
                               2636                 :                :     {
                               2637         [ +  + ]:             39 :         if (NUMERIC_IS_PINF(val))
                               2638                 :                :         {
                               2639         [ +  + ]:             18 :             if (NUMERIC_IS_PINF(base))
                               2640                 :             12 :                 result = true;  /* PINF = PINF */
                               2641                 :                :             else
                               2642                 :              6 :                 result = !less; /* PINF > any other non-NAN */
                               2643                 :                :         }
                               2644                 :                :         else                    /* val must be NINF */
                               2645                 :                :         {
                               2646         [ +  + ]:             21 :             if (NUMERIC_IS_NINF(base))
                               2647                 :             15 :                 result = true;  /* NINF = NINF */
                               2648                 :                :             else
                               2649                 :              6 :                 result = less;  /* NINF < anything else */
                               2650                 :                :         }
                               2651                 :                :     }
                               2652         [ +  + ]:            168 :     else if (NUMERIC_IS_SPECIAL(base))
                               2653                 :                :     {
                               2654         [ +  + ]:             12 :         if (NUMERIC_IS_NINF(base))
                               2655                 :              6 :             result = !less;     /* normal > NINF */
                               2656                 :                :         else
                               2657                 :              6 :             result = less;      /* normal < PINF */
                               2658                 :                :     }
                               2659                 :                :     else
                               2660                 :                :     {
                               2661                 :                :         /*
                               2662                 :                :          * Otherwise go ahead and compute base +/- offset.  While it's
                               2663                 :                :          * possible for this to overflow the numeric format, it's unlikely
                               2664                 :                :          * enough that we don't take measures to prevent it.
                               2665                 :                :          */
                               2666                 :                :         NumericVar  valv;
                               2667                 :                :         NumericVar  basev;
                               2668                 :                :         NumericVar  offsetv;
                               2669                 :                :         NumericVar  sum;
                               2670                 :                : 
 2241                          2671                 :            156 :         init_var_from_num(val, &valv);
                               2672                 :            156 :         init_var_from_num(base, &basev);
                               2673                 :            156 :         init_var_from_num(offset, &offsetv);
                               2674                 :            156 :         init_var(&sum);
                               2675                 :                : 
                               2676         [ +  + ]:            156 :         if (sub)
                               2677                 :             78 :             sub_var(&basev, &offsetv, &sum);
                               2678                 :                :         else
                               2679                 :             78 :             add_var(&basev, &offsetv, &sum);
                               2680                 :                : 
                               2681         [ +  + ]:            156 :         if (less)
                               2682                 :             78 :             result = (cmp_var(&valv, &sum) <= 0);
                               2683                 :                :         else
                               2684                 :             78 :             result = (cmp_var(&valv, &sum) >= 0);
                               2685                 :                : 
                               2686                 :            156 :         free_var(&sum);
                               2687                 :                :     }
                               2688                 :                : 
                               2689         [ +  - ]:            573 :     PG_FREE_IF_COPY(val, 0);
                               2690         [ +  - ]:            573 :     PG_FREE_IF_COPY(base, 1);
                               2691         [ -  + ]:            573 :     PG_FREE_IF_COPY(offset, 2);
                               2692                 :                : 
                               2693                 :            573 :     PG_RETURN_BOOL(result);
                               2694                 :                : }
                               2695                 :                : 
                               2696                 :                : Datum
 6186 neilc@samurai.com        2697                 :         303741 : hash_numeric(PG_FUNCTION_ARGS)
                               2698                 :                : {
 5995 bruce@momjian.us         2699                 :         303741 :     Numeric     key = PG_GETARG_NUMERIC(0);
                               2700                 :                :     Datum       digit_hash;
                               2701                 :                :     Datum       result;
                               2702                 :                :     int         weight;
                               2703                 :                :     int         start_offset;
                               2704                 :                :     int         end_offset;
                               2705                 :                :     int         i;
                               2706                 :                :     int         hash_len;
                               2707                 :                :     NumericDigit *digits;
                               2708                 :                : 
                               2709                 :                :     /* If it's NaN or infinity, don't try to hash the rest of the fields */
 1362 tgl@sss.pgh.pa.us        2710         [ -  + ]:         303741 :     if (NUMERIC_IS_SPECIAL(key))
 6186 neilc@samurai.com        2711                 :UBC           0 :         PG_RETURN_UINT32(0);
                               2712                 :                : 
 5003 rhaas@postgresql.org     2713   [ +  -  +  + ]:CBC      303741 :     weight = NUMERIC_WEIGHT(key);
 6186 neilc@samurai.com        2714                 :         303741 :     start_offset = 0;
 5995 bruce@momjian.us         2715                 :         303741 :     end_offset = 0;
                               2716                 :                : 
                               2717                 :                :     /*
                               2718                 :                :      * Omit any leading or trailing zeros from the input to the hash. The
                               2719                 :                :      * numeric implementation *should* guarantee that leading and trailing
                               2720                 :                :      * zeros are suppressed, but we're paranoid. Note that we measure the
                               2721                 :                :      * starting and ending offsets in units of NumericDigits, not bytes.
                               2722                 :                :      */
 5003 rhaas@postgresql.org     2723         [ +  - ]:         303741 :     digits = NUMERIC_DIGITS(key);
 6186 neilc@samurai.com        2724   [ +  -  +  + ]:         303741 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
                               2725                 :                :     {
 5003 rhaas@postgresql.org     2726         [ +  - ]:         302933 :         if (digits[i] != (NumericDigit) 0)
 6186 neilc@samurai.com        2727                 :         302933 :             break;
                               2728                 :                : 
 6186 neilc@samurai.com        2729                 :UBC           0 :         start_offset++;
                               2730                 :                : 
                               2731                 :                :         /*
                               2732                 :                :          * The weight is effectively the # of digits before the decimal point,
                               2733                 :                :          * so decrement it for each leading zero we skip.
                               2734                 :                :          */
                               2735                 :              0 :         weight--;
                               2736                 :                :     }
                               2737                 :                : 
                               2738                 :                :     /*
                               2739                 :                :      * If there are no non-zero digits, then the value of the number is zero,
                               2740                 :                :      * regardless of any other fields.
                               2741                 :                :      */
 6186 neilc@samurai.com        2742   [ +  -  +  + ]:CBC      303741 :     if (NUMERIC_NDIGITS(key) == start_offset)
                               2743                 :            808 :         PG_RETURN_UINT32(-1);
                               2744                 :                : 
                               2745   [ +  -  +  - ]:         302933 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
                               2746                 :                :     {
 5003 rhaas@postgresql.org     2747         [ +  - ]:         302933 :         if (digits[i] != (NumericDigit) 0)
 6186 neilc@samurai.com        2748                 :         302933 :             break;
                               2749                 :                : 
 6186 neilc@samurai.com        2750                 :UBC           0 :         end_offset++;
                               2751                 :                :     }
                               2752                 :                : 
                               2753                 :                :     /* If we get here, there should be at least one non-zero digit */
 6186 neilc@samurai.com        2754   [ +  -  -  + ]:CBC      302933 :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
                               2755                 :                : 
                               2756                 :                :     /*
                               2757                 :                :      * Note that we don't hash on the Numeric's scale, since two numerics can
                               2758                 :                :      * compare equal but have different scales. We also don't hash on the
                               2759                 :                :      * sign, although we could: since a sign difference implies inequality,
                               2760                 :                :      * this shouldn't affect correctness.
                               2761                 :                :      */
                               2762         [ +  - ]:         302933 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
                               2763         [ +  - ]:         302933 :     digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
                               2764                 :                :                           hash_len * sizeof(NumericDigit));
                               2765                 :                : 
                               2766                 :                :     /* Mix in the weight, via XOR */
                               2767                 :         302933 :     result = digit_hash ^ weight;
                               2768                 :                : 
                               2769                 :         302933 :     PG_RETURN_DATUM(result);
                               2770                 :                : }
                               2771                 :                : 
                               2772                 :                : /*
                               2773                 :                :  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
                               2774                 :                :  * Otherwise, similar to hash_numeric.
                               2775                 :                :  */
                               2776                 :                : Datum
 2418 rhaas@postgresql.org     2777                 :             42 : hash_numeric_extended(PG_FUNCTION_ARGS)
                               2778                 :                : {
                               2779                 :             42 :     Numeric     key = PG_GETARG_NUMERIC(0);
                               2780                 :             42 :     uint64      seed = PG_GETARG_INT64(1);
                               2781                 :                :     Datum       digit_hash;
                               2782                 :                :     Datum       result;
                               2783                 :                :     int         weight;
                               2784                 :                :     int         start_offset;
                               2785                 :                :     int         end_offset;
                               2786                 :                :     int         i;
                               2787                 :                :     int         hash_len;
                               2788                 :                :     NumericDigit *digits;
                               2789                 :                : 
                               2790                 :                :     /* If it's NaN or infinity, don't try to hash the rest of the fields */
 1362 tgl@sss.pgh.pa.us        2791         [ -  + ]:             42 :     if (NUMERIC_IS_SPECIAL(key))
 2418 rhaas@postgresql.org     2792                 :UBC           0 :         PG_RETURN_UINT64(seed);
                               2793                 :                : 
 2418 rhaas@postgresql.org     2794   [ +  -  -  + ]:CBC          42 :     weight = NUMERIC_WEIGHT(key);
                               2795                 :             42 :     start_offset = 0;
                               2796                 :             42 :     end_offset = 0;
                               2797                 :                : 
                               2798         [ +  - ]:             42 :     digits = NUMERIC_DIGITS(key);
                               2799   [ +  -  +  + ]:             42 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
                               2800                 :                :     {
                               2801         [ +  - ]:             36 :         if (digits[i] != (NumericDigit) 0)
                               2802                 :             36 :             break;
                               2803                 :                : 
 2418 rhaas@postgresql.org     2804                 :UBC           0 :         start_offset++;
                               2805                 :                : 
                               2806                 :              0 :         weight--;
                               2807                 :                :     }
                               2808                 :                : 
 2418 rhaas@postgresql.org     2809   [ +  -  +  + ]:CBC          42 :     if (NUMERIC_NDIGITS(key) == start_offset)
                               2810                 :              6 :         PG_RETURN_UINT64(seed - 1);
                               2811                 :                : 
                               2812   [ +  -  +  - ]:             36 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
                               2813                 :                :     {
                               2814         [ +  - ]:             36 :         if (digits[i] != (NumericDigit) 0)
                               2815                 :             36 :             break;
                               2816                 :                : 
 2418 rhaas@postgresql.org     2817                 :UBC           0 :         end_offset++;
                               2818                 :                :     }
                               2819                 :                : 
 2418 rhaas@postgresql.org     2820   [ +  -  -  + ]:CBC          36 :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
                               2821                 :                : 
                               2822         [ +  - ]:             36 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
                               2823         [ +  - ]:             36 :     digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
                               2824                 :             36 :                                                       + start_offset),
                               2825                 :                :                                    hash_len * sizeof(NumericDigit),
                               2826                 :                :                                    seed);
                               2827                 :                : 
 2417                          2828                 :             36 :     result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
                               2829                 :                : 
 2418                          2830                 :             36 :     PG_RETURN_DATUM(result);
                               2831                 :                : }
                               2832                 :                : 
                               2833                 :                : 
                               2834                 :                : /* ----------------------------------------------------------------------
                               2835                 :                :  *
                               2836                 :                :  * Basic arithmetic functions
                               2837                 :                :  *
                               2838                 :                :  * ----------------------------------------------------------------------
                               2839                 :                :  */
                               2840                 :                : 
                               2841                 :                : 
                               2842                 :                : /*
                               2843                 :                :  * numeric_add() -
                               2844                 :                :  *
                               2845                 :                :  *  Add two numerics
                               2846                 :                :  */
                               2847                 :                : Datum
 8660 tgl@sss.pgh.pa.us        2848                 :         126026 : numeric_add(PG_FUNCTION_ARGS)
                               2849                 :                : {
                               2850                 :         126026 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2851                 :         126026 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2852                 :                :     Numeric     res;
                               2853                 :                : 
 1856 akorotkov@postgresql     2854                 :         126026 :     res = numeric_add_opt_error(num1, num2, NULL);
                               2855                 :                : 
                               2856                 :         126026 :     PG_RETURN_NUMERIC(res);
                               2857                 :                : }
                               2858                 :                : 
                               2859                 :                : /*
                               2860                 :                :  * numeric_add_opt_error() -
                               2861                 :                :  *
                               2862                 :                :  *  Internal version of numeric_add().  If "*have_error" flag is provided,
                               2863                 :                :  *  on error it's set to true, NULL returned.  This is helpful when caller
                               2864                 :                :  *  need to handle errors by itself.
                               2865                 :                :  */
                               2866                 :                : Numeric
                               2867                 :         126545 : numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
                               2868                 :                : {
                               2869                 :                :     NumericVar  arg1;
                               2870                 :                :     NumericVar  arg2;
                               2871                 :                :     NumericVar  result;
                               2872                 :                :     Numeric     res;
                               2873                 :                : 
                               2874                 :                :     /*
                               2875                 :                :      * Handle NaN and infinities
                               2876                 :                :      */
 1362 tgl@sss.pgh.pa.us        2877   [ +  +  +  + ]:         126545 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               2878                 :                :     {
                               2879   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               2880                 :             39 :             return make_result(&const_nan);
                               2881         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               2882                 :                :         {
                               2883         [ +  + ]:             18 :             if (NUMERIC_IS_NINF(num2))
                               2884                 :              3 :                 return make_result(&const_nan); /* Inf + -Inf */
                               2885                 :                :             else
                               2886                 :             15 :                 return make_result(&const_pinf);
                               2887                 :                :         }
                               2888         [ +  + ]:             42 :         if (NUMERIC_IS_NINF(num1))
                               2889                 :                :         {
                               2890         [ +  + ]:             18 :             if (NUMERIC_IS_PINF(num2))
                               2891                 :              3 :                 return make_result(&const_nan); /* -Inf + Inf */
                               2892                 :                :             else
                               2893                 :             15 :                 return make_result(&const_ninf);
                               2894                 :                :         }
                               2895                 :                :         /* by here, num1 must be finite, so num2 is not */
                               2896         [ +  + ]:             24 :         if (NUMERIC_IS_PINF(num2))
                               2897                 :             12 :             return make_result(&const_pinf);
                               2898         [ -  + ]:             12 :         Assert(NUMERIC_IS_NINF(num2));
                               2899                 :             12 :         return make_result(&const_ninf);
                               2900                 :                :     }
                               2901                 :                : 
                               2902                 :                :     /*
                               2903                 :                :      * Unpack the values, let add_var() compute the result and return it.
                               2904                 :                :      */
 4162 heikki.linnakangas@i     2905                 :         126446 :     init_var_from_num(num1, &arg1);
                               2906                 :         126446 :     init_var_from_num(num2, &arg2);
                               2907                 :                : 
                               2908                 :         126446 :     init_var(&result);
 9237 JanWieck@Yahoo.com       2909                 :         126446 :     add_var(&arg1, &arg2, &result);
                               2910                 :                : 
 1856 akorotkov@postgresql     2911                 :         126446 :     res = make_result_opt_error(&result, have_error);
                               2912                 :                : 
 9237 JanWieck@Yahoo.com       2913                 :         126446 :     free_var(&result);
                               2914                 :                : 
 1856 akorotkov@postgresql     2915                 :         126446 :     return res;
                               2916                 :                : }
                               2917                 :                : 
                               2918                 :                : 
                               2919                 :                : /*
                               2920                 :                :  * numeric_sub() -
                               2921                 :                :  *
                               2922                 :                :  *  Subtract one numeric from another
                               2923                 :                :  */
                               2924                 :                : Datum
 8660 tgl@sss.pgh.pa.us        2925                 :          46324 : numeric_sub(PG_FUNCTION_ARGS)
                               2926                 :                : {
                               2927                 :          46324 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2928                 :          46324 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2929                 :                :     Numeric     res;
                               2930                 :                : 
 1856 akorotkov@postgresql     2931                 :          46324 :     res = numeric_sub_opt_error(num1, num2, NULL);
                               2932                 :                : 
                               2933                 :          46324 :     PG_RETURN_NUMERIC(res);
                               2934                 :                : }
                               2935                 :                : 
                               2936                 :                : 
                               2937                 :                : /*
                               2938                 :                :  * numeric_sub_opt_error() -
                               2939                 :                :  *
                               2940                 :                :  *  Internal version of numeric_sub().  If "*have_error" flag is provided,
                               2941                 :                :  *  on error it's set to true, NULL returned.  This is helpful when caller
                               2942                 :                :  *  need to handle errors by itself.
                               2943                 :                :  */
                               2944                 :                : Numeric
                               2945                 :          46399 : numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
                               2946                 :                : {
                               2947                 :                :     NumericVar  arg1;
                               2948                 :                :     NumericVar  arg2;
                               2949                 :                :     NumericVar  result;
                               2950                 :                :     Numeric     res;
                               2951                 :                : 
                               2952                 :                :     /*
                               2953                 :                :      * Handle NaN and infinities
                               2954                 :                :      */
 1362 tgl@sss.pgh.pa.us        2955   [ +  +  +  + ]:          46399 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               2956                 :                :     {
                               2957   [ +  +  +  + ]:           1073 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               2958                 :           1013 :             return make_result(&const_nan);
                               2959         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               2960                 :                :         {
                               2961         [ +  + ]:             18 :             if (NUMERIC_IS_PINF(num2))
                               2962                 :              3 :                 return make_result(&const_nan); /* Inf - Inf */
                               2963                 :                :             else
                               2964                 :             15 :                 return make_result(&const_pinf);
                               2965                 :                :         }
                               2966         [ +  + ]:             42 :         if (NUMERIC_IS_NINF(num1))
                               2967                 :                :         {
                               2968         [ +  + ]:             18 :             if (NUMERIC_IS_NINF(num2))
                               2969                 :              3 :                 return make_result(&const_nan); /* -Inf - -Inf */
                               2970                 :                :             else
                               2971                 :             15 :                 return make_result(&const_ninf);
                               2972                 :                :         }
                               2973                 :                :         /* by here, num1 must be finite, so num2 is not */
                               2974         [ +  + ]:             24 :         if (NUMERIC_IS_PINF(num2))
                               2975                 :             12 :             return make_result(&const_ninf);
                               2976         [ -  + ]:             12 :         Assert(NUMERIC_IS_NINF(num2));
                               2977                 :             12 :         return make_result(&const_pinf);
                               2978                 :                :     }
                               2979                 :                : 
                               2980                 :                :     /*
                               2981                 :                :      * Unpack the values, let sub_var() compute the result and return it.
                               2982                 :                :      */
 4162 heikki.linnakangas@i     2983                 :          45326 :     init_var_from_num(num1, &arg1);
                               2984                 :          45326 :     init_var_from_num(num2, &arg2);
                               2985                 :                : 
                               2986                 :          45326 :     init_var(&result);
 9237 JanWieck@Yahoo.com       2987                 :          45326 :     sub_var(&arg1, &arg2, &result);
                               2988                 :                : 
 1856 akorotkov@postgresql     2989                 :          45326 :     res = make_result_opt_error(&result, have_error);
                               2990                 :                : 
 9237 JanWieck@Yahoo.com       2991                 :          45326 :     free_var(&result);
                               2992                 :                : 
 1856 akorotkov@postgresql     2993                 :          45326 :     return res;
                               2994                 :                : }
                               2995                 :                : 
                               2996                 :                : 
                               2997                 :                : /*
                               2998                 :                :  * numeric_mul() -
                               2999                 :                :  *
                               3000                 :                :  *  Calculate the product of two numerics
                               3001                 :                :  */
                               3002                 :                : Datum
 8660 tgl@sss.pgh.pa.us        3003                 :         244839 : numeric_mul(PG_FUNCTION_ARGS)
                               3004                 :                : {
                               3005                 :         244839 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3006                 :         244839 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3007                 :                :     Numeric     res;
                               3008                 :                : 
 1856 akorotkov@postgresql     3009                 :         244839 :     res = numeric_mul_opt_error(num1, num2, NULL);
                               3010                 :                : 
                               3011                 :         244839 :     PG_RETURN_NUMERIC(res);
                               3012                 :                : }
                               3013                 :                : 
                               3014                 :                : 
                               3015                 :                : /*
                               3016                 :                :  * numeric_mul_opt_error() -
                               3017                 :                :  *
                               3018                 :                :  *  Internal version of numeric_mul().  If "*have_error" flag is provided,
                               3019                 :                :  *  on error it's set to true, NULL returned.  This is helpful when caller
                               3020                 :                :  *  need to handle errors by itself.
                               3021                 :                :  */
                               3022                 :                : Numeric
                               3023                 :         244857 : numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
                               3024                 :                : {
                               3025                 :                :     NumericVar  arg1;
                               3026                 :                :     NumericVar  arg2;
                               3027                 :                :     NumericVar  result;
                               3028                 :                :     Numeric     res;
                               3029                 :                : 
                               3030                 :                :     /*
                               3031                 :                :      * Handle NaN and infinities
                               3032                 :                :      */
 1362 tgl@sss.pgh.pa.us        3033   [ +  +  +  + ]:         244857 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3034                 :                :     {
                               3035   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3036                 :             39 :             return make_result(&const_nan);
                               3037         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               3038                 :                :         {
                               3039   [ +  +  +  - ]:             18 :             switch (numeric_sign_internal(num2))
                               3040                 :                :             {
                               3041                 :              3 :                 case 0:
                               3042                 :              3 :                     return make_result(&const_nan); /* Inf * 0 */
                               3043                 :              9 :                 case 1:
                               3044                 :              9 :                     return make_result(&const_pinf);
                               3045                 :              6 :                 case -1:
                               3046                 :              6 :                     return make_result(&const_ninf);
                               3047                 :                :             }
 1362 tgl@sss.pgh.pa.us        3048                 :UBC           0 :             Assert(false);
                               3049                 :                :         }
 1362 tgl@sss.pgh.pa.us        3050         [ +  + ]:CBC          42 :         if (NUMERIC_IS_NINF(num1))
                               3051                 :                :         {
                               3052   [ +  +  +  - ]:             18 :             switch (numeric_sign_internal(num2))
                               3053                 :                :             {
                               3054                 :              3 :                 case 0:
                               3055                 :              3 :                     return make_result(&const_nan); /* -Inf * 0 */
                               3056                 :              9 :                 case 1:
                               3057                 :              9 :                     return make_result(&const_ninf);
                               3058                 :              6 :                 case -1:
                               3059                 :              6 :                     return make_result(&const_pinf);
                               3060                 :                :             }
 1362 tgl@sss.pgh.pa.us        3061                 :UBC           0 :             Assert(false);
                               3062                 :                :         }
                               3063                 :                :         /* by here, num1 must be finite, so num2 is not */
 1362 tgl@sss.pgh.pa.us        3064         [ +  + ]:CBC          24 :         if (NUMERIC_IS_PINF(num2))
                               3065                 :                :         {
                               3066   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num1))
                               3067                 :                :             {
                               3068                 :              3 :                 case 0:
                               3069                 :              3 :                     return make_result(&const_nan); /* 0 * Inf */
                               3070                 :              6 :                 case 1:
                               3071                 :              6 :                     return make_result(&const_pinf);
                               3072                 :              3 :                 case -1:
                               3073                 :              3 :                     return make_result(&const_ninf);
                               3074                 :                :             }
 1362 tgl@sss.pgh.pa.us        3075                 :UBC           0 :             Assert(false);
                               3076                 :                :         }
 1362 tgl@sss.pgh.pa.us        3077         [ -  + ]:CBC          12 :         Assert(NUMERIC_IS_NINF(num2));
                               3078   [ +  +  +  - ]:             12 :         switch (numeric_sign_internal(num1))
                               3079                 :                :         {
                               3080                 :              3 :             case 0:
                               3081                 :              3 :                 return make_result(&const_nan); /* 0 * -Inf */
                               3082                 :              6 :             case 1:
                               3083                 :              6 :                 return make_result(&const_ninf);
                               3084                 :              3 :             case -1:
                               3085                 :              3 :                 return make_result(&const_pinf);
                               3086                 :                :         }
 1362 tgl@sss.pgh.pa.us        3087                 :UBC           0 :         Assert(false);
                               3088                 :                :     }
                               3089                 :                : 
                               3090                 :                :     /*
                               3091                 :                :      * Unpack the values, let mul_var() compute the result and return it.
                               3092                 :                :      * Unlike add_var() and sub_var(), mul_var() will round its result. In the
                               3093                 :                :      * case of numeric_mul(), which is invoked for the * operator on numerics,
                               3094                 :                :      * we request exact representation for the product (rscale = sum(dscale of
                               3095                 :                :      * arg1, dscale of arg2)).  If the exact result has more digits after the
                               3096                 :                :      * decimal point than can be stored in a numeric, we round it.  Rounding
                               3097                 :                :      * after computing the exact result ensures that the final result is
                               3098                 :                :      * correctly rounded (rounding in mul_var() using a truncated product
                               3099                 :                :      * would not guarantee this).
                               3100                 :                :      */
 4162 heikki.linnakangas@i     3101                 :CBC      244758 :     init_var_from_num(num1, &arg1);
                               3102                 :         244758 :     init_var_from_num(num2, &arg2);
                               3103                 :                : 
                               3104                 :         244758 :     init_var(&result);
 7695 tgl@sss.pgh.pa.us        3105                 :         244758 :     mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
                               3106                 :                : 
 1009 dean.a.rasheed@gmail     3107         [ +  + ]:         244758 :     if (result.dscale > NUMERIC_DSCALE_MAX)
                               3108                 :              3 :         round_var(&result, NUMERIC_DSCALE_MAX);
                               3109                 :                : 
 1856 akorotkov@postgresql     3110                 :         244758 :     res = make_result_opt_error(&result, have_error);
                               3111                 :                : 
 9237 JanWieck@Yahoo.com       3112                 :         244758 :     free_var(&result);
                               3113                 :                : 
 1856 akorotkov@postgresql     3114                 :         244758 :     return res;
                               3115                 :                : }
                               3116                 :                : 
                               3117                 :                : 
                               3118                 :                : /*
                               3119                 :                :  * numeric_div() -
                               3120                 :                :  *
                               3121                 :                :  *  Divide one numeric into another
                               3122                 :                :  */
                               3123                 :                : Datum
 8660 tgl@sss.pgh.pa.us        3124                 :          75711 : numeric_div(PG_FUNCTION_ARGS)
                               3125                 :                : {
                               3126                 :          75711 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3127                 :          75711 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3128                 :                :     Numeric     res;
                               3129                 :                : 
 1856 akorotkov@postgresql     3130                 :          75711 :     res = numeric_div_opt_error(num1, num2, NULL);
                               3131                 :                : 
                               3132                 :          75695 :     PG_RETURN_NUMERIC(res);
                               3133                 :                : }
                               3134                 :                : 
                               3135                 :                : 
                               3136                 :                : /*
                               3137                 :                :  * numeric_div_opt_error() -
                               3138                 :                :  *
                               3139                 :                :  *  Internal version of numeric_div().  If "*have_error" flag is provided,
                               3140                 :                :  *  on error it's set to true, NULL returned.  This is helpful when caller
                               3141                 :                :  *  need to handle errors by itself.
                               3142                 :                :  */
                               3143                 :                : Numeric
                               3144                 :          76131 : numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
                               3145                 :                : {
                               3146                 :                :     NumericVar  arg1;
                               3147                 :                :     NumericVar  arg2;
                               3148                 :                :     NumericVar  result;
                               3149                 :                :     Numeric     res;
                               3150                 :                :     int         rscale;
                               3151                 :                : 
 1714 michael@paquier.xyz      3152         [ +  + ]:          76131 :     if (have_error)
                               3153                 :             24 :         *have_error = false;
                               3154                 :                : 
                               3155                 :                :     /*
                               3156                 :                :      * Handle NaN and infinities
                               3157                 :                :      */
 1362 tgl@sss.pgh.pa.us        3158   [ +  +  +  + ]:          76131 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3159                 :                :     {
                               3160   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3161                 :             39 :             return make_result(&const_nan);
                               3162         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               3163                 :                :         {
                               3164         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3165                 :              6 :                 return make_result(&const_nan); /* Inf / [-]Inf */
                               3166   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3167                 :                :             {
                               3168                 :              3 :                 case 0:
                               3169         [ -  + ]:              3 :                     if (have_error)
                               3170                 :                :                     {
 1362 tgl@sss.pgh.pa.us        3171                 :UBC           0 :                         *have_error = true;
                               3172                 :              0 :                         return NULL;
                               3173                 :                :                     }
 1362 tgl@sss.pgh.pa.us        3174         [ +  - ]:CBC           3 :                     ereport(ERROR,
                               3175                 :                :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3176                 :                :                              errmsg("division by zero")));
                               3177                 :                :                     break;
                               3178                 :              6 :                 case 1:
                               3179                 :              6 :                     return make_result(&const_pinf);
                               3180                 :              3 :                 case -1:
                               3181                 :              3 :                     return make_result(&const_ninf);
                               3182                 :                :             }
 1362 tgl@sss.pgh.pa.us        3183                 :UBC           0 :             Assert(false);
                               3184                 :                :         }
 1362 tgl@sss.pgh.pa.us        3185         [ +  + ]:CBC          42 :         if (NUMERIC_IS_NINF(num1))
                               3186                 :                :         {
                               3187         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3188                 :              6 :                 return make_result(&const_nan); /* -Inf / [-]Inf */
                               3189   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3190                 :                :             {
                               3191                 :              3 :                 case 0:
                               3192         [ -  + ]:              3 :                     if (have_error)
                               3193                 :                :                     {
 1362 tgl@sss.pgh.pa.us        3194                 :UBC           0 :                         *have_error = true;
                               3195                 :              0 :                         return NULL;
                               3196                 :                :                     }
 1362 tgl@sss.pgh.pa.us        3197         [ +  - ]:CBC           3 :                     ereport(ERROR,
                               3198                 :                :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3199                 :                :                              errmsg("division by zero")));
                               3200                 :                :                     break;
                               3201                 :              6 :                 case 1:
                               3202                 :              6 :                     return make_result(&const_ninf);
                               3203                 :              3 :                 case -1:
                               3204                 :              3 :                     return make_result(&const_pinf);
                               3205                 :                :             }
 1362 tgl@sss.pgh.pa.us        3206                 :UBC           0 :             Assert(false);
                               3207                 :                :         }
                               3208                 :                :         /* by here, num1 must be finite, so num2 is not */
                               3209                 :                : 
                               3210                 :                :         /*
                               3211                 :                :          * POSIX would have us return zero or minus zero if num1 is zero, and
                               3212                 :                :          * otherwise throw an underflow error.  But the numeric type doesn't
                               3213                 :                :          * really do underflow, so let's just return zero.
                               3214                 :                :          */
 1362 tgl@sss.pgh.pa.us        3215                 :CBC          24 :         return make_result(&const_zero);
                               3216                 :                :     }
                               3217                 :                : 
                               3218                 :                :     /*
                               3219                 :                :      * Unpack the arguments
                               3220                 :                :      */
 4162 heikki.linnakangas@i     3221                 :          76032 :     init_var_from_num(num1, &arg1);
                               3222                 :          76032 :     init_var_from_num(num2, &arg2);
                               3223                 :                : 
                               3224                 :          76032 :     init_var(&result);
                               3225                 :                : 
                               3226                 :                :     /*
                               3227                 :                :      * Select scale for division result
                               3228                 :                :      */
 7695 tgl@sss.pgh.pa.us        3229                 :          76032 :     rscale = select_div_scale(&arg1, &arg2);
                               3230                 :                : 
                               3231                 :                :     /*
                               3232                 :                :      * If "have_error" is provided, check for division by zero here
                               3233                 :                :      */
 1856 akorotkov@postgresql     3234   [ +  +  +  +  :          76032 :     if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
                                              -  + ]
                               3235                 :                :     {
                               3236                 :              6 :         *have_error = true;
                               3237                 :              6 :         return NULL;
                               3238                 :                :     }
                               3239                 :                : 
                               3240                 :                :     /*
                               3241                 :                :      * Do the divide and return the result
                               3242                 :                :      */
 6889 bruce@momjian.us         3243                 :          76026 :     div_var(&arg1, &arg2, &result, rscale, true);
                               3244                 :                : 
 1856 akorotkov@postgresql     3245                 :          76007 :     res = make_result_opt_error(&result, have_error);
                               3246                 :                : 
 9237 JanWieck@Yahoo.com       3247                 :          76007 :     free_var(&result);
                               3248                 :                : 
 1856 akorotkov@postgresql     3249                 :          76007 :     return res;
                               3250                 :                : }
                               3251                 :                : 
                               3252                 :                : 
                               3253                 :                : /*
                               3254                 :                :  * numeric_div_trunc() -
                               3255                 :                :  *
                               3256                 :                :  *  Divide one numeric into another, truncating the result to an integer
                               3257                 :                :  */
                               3258                 :                : Datum
 5854 tgl@sss.pgh.pa.us        3259                 :            600 : numeric_div_trunc(PG_FUNCTION_ARGS)
                               3260                 :                : {
                               3261                 :            600 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3262                 :            600 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3263                 :                :     NumericVar  arg1;
                               3264                 :                :     NumericVar  arg2;
                               3265                 :                :     NumericVar  result;
                               3266                 :                :     Numeric     res;
                               3267                 :                : 
                               3268                 :                :     /*
                               3269                 :                :      * Handle NaN and infinities
                               3270                 :                :      */
 1362                          3271   [ +  +  +  + ]:            600 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3272                 :                :     {
                               3273   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3274                 :             39 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3275         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               3276                 :                :         {
                               3277         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3278                 :              6 :                 PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
                               3279   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3280                 :                :             {
                               3281                 :              3 :                 case 0:
                               3282         [ +  - ]:              3 :                     ereport(ERROR,
                               3283                 :                :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3284                 :                :                              errmsg("division by zero")));
                               3285                 :                :                     break;
                               3286                 :              6 :                 case 1:
                               3287                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_pinf));
                               3288                 :              3 :                 case -1:
                               3289                 :              3 :                     PG_RETURN_NUMERIC(make_result(&const_ninf));
                               3290                 :                :             }
 1362 tgl@sss.pgh.pa.us        3291                 :UBC           0 :             Assert(false);
                               3292                 :                :         }
 1362 tgl@sss.pgh.pa.us        3293         [ +  + ]:CBC          42 :         if (NUMERIC_IS_NINF(num1))
                               3294                 :                :         {
                               3295         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3296                 :              6 :                 PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
                               3297   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3298                 :                :             {
                               3299                 :              3 :                 case 0:
                               3300         [ +  - ]:              3 :                     ereport(ERROR,
                               3301                 :                :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3302                 :                :                              errmsg("division by zero")));
                               3303                 :                :                     break;
                               3304                 :              6 :                 case 1:
                               3305                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_ninf));
                               3306                 :              3 :                 case -1:
                               3307                 :              3 :                     PG_RETURN_NUMERIC(make_result(&const_pinf));
                               3308                 :                :             }
 1362 tgl@sss.pgh.pa.us        3309                 :UBC           0 :             Assert(false);
                               3310                 :                :         }
                               3311                 :                :         /* by here, num1 must be finite, so num2 is not */
                               3312                 :                : 
                               3313                 :                :         /*
                               3314                 :                :          * POSIX would have us return zero or minus zero if num1 is zero, and
                               3315                 :                :          * otherwise throw an underflow error.  But the numeric type doesn't
                               3316                 :                :          * really do underflow, so let's just return zero.
                               3317                 :                :          */
 1362 tgl@sss.pgh.pa.us        3318                 :CBC          24 :         PG_RETURN_NUMERIC(make_result(&const_zero));
                               3319                 :                :     }
                               3320                 :                : 
                               3321                 :                :     /*
                               3322                 :                :      * Unpack the arguments
                               3323                 :                :      */
 4162 heikki.linnakangas@i     3324                 :            501 :     init_var_from_num(num1, &arg1);
                               3325                 :            501 :     init_var_from_num(num2, &arg2);
                               3326                 :                : 
                               3327                 :            501 :     init_var(&result);
                               3328                 :                : 
                               3329                 :                :     /*
                               3330                 :                :      * Do the divide and return the result
                               3331                 :                :      */
 5854 tgl@sss.pgh.pa.us        3332                 :            501 :     div_var(&arg1, &arg2, &result, 0, false);
                               3333                 :                : 
                               3334                 :            498 :     res = make_result(&result);
                               3335                 :                : 
                               3336                 :            498 :     free_var(&result);
                               3337                 :                : 
                               3338                 :            498 :     PG_RETURN_NUMERIC(res);
                               3339                 :                : }
                               3340                 :                : 
                               3341                 :                : 
                               3342                 :                : /*
                               3343                 :                :  * numeric_mod() -
                               3344                 :                :  *
                               3345                 :                :  *  Calculate the modulo of two numerics
                               3346                 :                :  */
                               3347                 :                : Datum
 8660                          3348                 :          27064 : numeric_mod(PG_FUNCTION_ARGS)
                               3349                 :                : {
                               3350                 :          27064 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3351                 :          27064 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3352                 :                :     Numeric     res;
                               3353                 :                : 
 1856 akorotkov@postgresql     3354                 :          27064 :     res = numeric_mod_opt_error(num1, num2, NULL);
                               3355                 :                : 
                               3356                 :          27055 :     PG_RETURN_NUMERIC(res);
                               3357                 :                : }
                               3358                 :                : 
                               3359                 :                : 
                               3360                 :                : /*
                               3361                 :                :  * numeric_mod_opt_error() -
                               3362                 :                :  *
                               3363                 :                :  *  Internal version of numeric_mod().  If "*have_error" flag is provided,
                               3364                 :                :  *  on error it's set to true, NULL returned.  This is helpful when caller
                               3365                 :                :  *  need to handle errors by itself.
                               3366                 :                :  */
                               3367                 :                : Numeric
                               3368                 :          27070 : numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
                               3369                 :                : {
                               3370                 :                :     Numeric     res;
                               3371                 :                :     NumericVar  arg1;
                               3372                 :                :     NumericVar  arg2;
                               3373                 :                :     NumericVar  result;
                               3374                 :                : 
 1714 michael@paquier.xyz      3375         [ -  + ]:          27070 :     if (have_error)
 1714 michael@paquier.xyz      3376                 :UBC           0 :         *have_error = false;
                               3377                 :                : 
                               3378                 :                :     /*
                               3379                 :                :      * Handle NaN and infinities.  We follow POSIX fmod() on this, except that
                               3380                 :                :      * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
                               3381                 :                :      * returning NaN.  We choose to throw error only for y-is-zero.
                               3382                 :                :      */
 1362 tgl@sss.pgh.pa.us        3383   [ +  +  +  + ]:CBC       27070 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3384                 :                :     {
                               3385   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3386                 :             39 :             return make_result(&const_nan);
                               3387         [ +  + ]:             60 :         if (NUMERIC_IS_INF(num1))
                               3388                 :                :         {
                               3389         [ +  + ]:             36 :             if (numeric_sign_internal(num2) == 0)
                               3390                 :                :             {
                               3391         [ -  + ]:              6 :                 if (have_error)
                               3392                 :                :                 {
 1362 tgl@sss.pgh.pa.us        3393                 :UBC           0 :                     *have_error = true;
                               3394                 :              0 :                     return NULL;
                               3395                 :                :                 }
 1362 tgl@sss.pgh.pa.us        3396         [ +  - ]:CBC           6 :                 ereport(ERROR,
                               3397                 :                :                         (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3398                 :                :                          errmsg("division by zero")));
                               3399                 :                :             }
                               3400                 :                :             /* Inf % any nonzero = NaN */
                               3401                 :             30 :             return make_result(&const_nan);
                               3402                 :                :         }
                               3403                 :                :         /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
                               3404                 :             24 :         return duplicate_numeric(num1);
                               3405                 :                :     }
                               3406                 :                : 
 4162 heikki.linnakangas@i     3407                 :          26971 :     init_var_from_num(num1, &arg1);
                               3408                 :          26971 :     init_var_from_num(num2, &arg2);
                               3409                 :                : 
                               3410                 :          26971 :     init_var(&result);
                               3411                 :                : 
                               3412                 :                :     /*
                               3413                 :                :      * If "have_error" is provided, check for division by zero here
                               3414                 :                :      */
 1856 akorotkov@postgresql     3415   [ -  +  -  -  :          26971 :     if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
                                              -  - ]
                               3416                 :                :     {
 1856 akorotkov@postgresql     3417                 :UBC           0 :         *have_error = true;
                               3418                 :              0 :         return NULL;
                               3419                 :                :     }
                               3420                 :                : 
 9237 JanWieck@Yahoo.com       3421                 :CBC       26971 :     mod_var(&arg1, &arg2, &result);
                               3422                 :                : 
 1856 akorotkov@postgresql     3423                 :          26965 :     res = make_result_opt_error(&result, NULL);
                               3424                 :                : 
 9237 JanWieck@Yahoo.com       3425                 :          26965 :     free_var(&result);
                               3426                 :                : 
 1856 akorotkov@postgresql     3427                 :          26965 :     return res;
                               3428                 :                : }
                               3429                 :                : 
                               3430                 :                : 
                               3431                 :                : /*
                               3432                 :                :  * numeric_inc() -
                               3433                 :                :  *
                               3434                 :                :  *  Increment a number by one
                               3435                 :                :  */
                               3436                 :                : Datum
 8660 tgl@sss.pgh.pa.us        3437                 :             24 : numeric_inc(PG_FUNCTION_ARGS)
                               3438                 :                : {
                               3439                 :             24 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3440                 :                :     NumericVar  arg;
                               3441                 :                :     Numeric     res;
                               3442                 :                : 
                               3443                 :                :     /*
                               3444                 :                :      * Handle NaN and infinities
                               3445                 :                :      */
 1362                          3446         [ +  + ]:             24 :     if (NUMERIC_IS_SPECIAL(num))
                               3447                 :              9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3448                 :                : 
                               3449                 :                :     /*
                               3450                 :                :      * Compute the result and return it
                               3451                 :                :      */
 4162 heikki.linnakangas@i     3452                 :             15 :     init_var_from_num(num, &arg);
                               3453                 :                : 
 9237 JanWieck@Yahoo.com       3454                 :             15 :     add_var(&arg, &const_one, &arg);
                               3455                 :                : 
                               3456                 :             15 :     res = make_result(&arg);
                               3457                 :                : 
                               3458                 :             15 :     free_var(&arg);
                               3459                 :                : 
 8660 tgl@sss.pgh.pa.us        3460                 :             15 :     PG_RETURN_NUMERIC(res);
                               3461                 :                : }
                               3462                 :                : 
                               3463                 :                : 
                               3464                 :                : /*
                               3465                 :                :  * numeric_smaller() -
                               3466                 :                :  *
                               3467                 :                :  *  Return the smaller of two numbers
                               3468                 :                :  */
                               3469                 :                : Datum
                               3470                 :            399 : numeric_smaller(PG_FUNCTION_ARGS)
                               3471                 :                : {
                               3472                 :            399 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3473                 :            399 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3474                 :                : 
                               3475                 :                :     /*
                               3476                 :                :      * Use cmp_numerics so that this will agree with the comparison operators,
                               3477                 :                :      * particularly as regards comparisons involving NaN.
                               3478                 :                :      */
 7564                          3479         [ +  + ]:            399 :     if (cmp_numerics(num1, num2) < 0)
                               3480                 :            321 :         PG_RETURN_NUMERIC(num1);
                               3481                 :                :     else
                               3482                 :             78 :         PG_RETURN_NUMERIC(num2);
                               3483                 :                : }
                               3484                 :                : 
                               3485                 :                : 
                               3486                 :                : /*
                               3487                 :                :  * numeric_larger() -
                               3488                 :                :  *
                               3489                 :                :  *  Return the larger of two numbers
                               3490                 :                :  */
                               3491                 :                : Datum
 8660                          3492                 :           9315 : numeric_larger(PG_FUNCTION_ARGS)
                               3493                 :                : {
                               3494                 :           9315 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3495                 :           9315 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3496                 :                : 
                               3497                 :                :     /*
                               3498                 :                :      * Use cmp_numerics so that this will agree with the comparison operators,
                               3499                 :                :      * particularly as regards comparisons involving NaN.
                               3500                 :                :      */
 7564                          3501         [ +  + ]:           9315 :     if (cmp_numerics(num1, num2) > 0)
                               3502                 :           8954 :         PG_RETURN_NUMERIC(num1);
                               3503                 :                :     else
                               3504                 :            361 :         PG_RETURN_NUMERIC(num2);
                               3505                 :                : }
                               3506                 :                : 
                               3507                 :                : 
                               3508                 :                : /* ----------------------------------------------------------------------
                               3509                 :                :  *
                               3510                 :                :  * Advanced math functions
                               3511                 :                :  *
                               3512                 :                :  * ----------------------------------------------------------------------
                               3513                 :                :  */
                               3514                 :                : 
                               3515                 :                : /*
                               3516                 :                :  * numeric_gcd() -
                               3517                 :                :  *
                               3518                 :                :  *  Calculate the greatest common divisor of two numerics
                               3519                 :                :  */
                               3520                 :                : Datum
 1541 dean.a.rasheed@gmail     3521                 :            108 : numeric_gcd(PG_FUNCTION_ARGS)
                               3522                 :                : {
                               3523                 :            108 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3524                 :            108 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3525                 :                :     NumericVar  arg1;
                               3526                 :                :     NumericVar  arg2;
                               3527                 :                :     NumericVar  result;
                               3528                 :                :     Numeric     res;
                               3529                 :                : 
                               3530                 :                :     /*
                               3531                 :                :      * Handle NaN and infinities: we consider the result to be NaN in all such
                               3532                 :                :      * cases.
                               3533                 :                :      */
 1362 tgl@sss.pgh.pa.us        3534   [ +  +  +  + ]:            108 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 1541 dean.a.rasheed@gmail     3535                 :             48 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               3536                 :                : 
                               3537                 :                :     /*
                               3538                 :                :      * Unpack the arguments
                               3539                 :                :      */
                               3540                 :             60 :     init_var_from_num(num1, &arg1);
                               3541                 :             60 :     init_var_from_num(num2, &arg2);
                               3542                 :                : 
                               3543                 :             60 :     init_var(&result);
                               3544                 :                : 
                               3545                 :                :     /*
                               3546                 :                :      * Find the GCD and return the result
                               3547                 :                :      */
                               3548                 :             60 :     gcd_var(&arg1, &arg2, &result);
                               3549                 :                : 
                               3550                 :             60 :     res = make_result(&result);
                               3551                 :                : 
                               3552                 :             60 :     free_var(&result);
                               3553                 :                : 
                               3554                 :             60 :     PG_RETURN_NUMERIC(res);
                               3555                 :                : }
                               3556                 :                : 
                               3557                 :                : 
                               3558                 :                : /*
                               3559                 :                :  * numeric_lcm() -
                               3560                 :                :  *
                               3561                 :                :  *  Calculate the least common multiple of two numerics
                               3562                 :                :  */
                               3563                 :                : Datum
                               3564                 :            123 : numeric_lcm(PG_FUNCTION_ARGS)
                               3565                 :                : {
                               3566                 :            123 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3567                 :            123 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3568                 :                :     NumericVar  arg1;
                               3569                 :                :     NumericVar  arg2;
                               3570                 :                :     NumericVar  result;
                               3571                 :                :     Numeric     res;
                               3572                 :                : 
                               3573                 :                :     /*
                               3574                 :                :      * Handle NaN and infinities: we consider the result to be NaN in all such
                               3575                 :                :      * cases.
                               3576                 :                :      */
 1362 tgl@sss.pgh.pa.us        3577   [ +  +  +  + ]:            123 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 1541 dean.a.rasheed@gmail     3578                 :             48 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               3579                 :                : 
                               3580                 :                :     /*
                               3581                 :                :      * Unpack the arguments
                               3582                 :                :      */
                               3583                 :             75 :     init_var_from_num(num1, &arg1);
                               3584                 :             75 :     init_var_from_num(num2, &arg2);
                               3585                 :                : 
                               3586                 :             75 :     init_var(&result);
                               3587                 :                : 
                               3588                 :                :     /*
                               3589                 :                :      * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
                               3590                 :                :      * zero if either input is zero.
                               3591                 :                :      *
                               3592                 :                :      * Note that the division is guaranteed to be exact, returning an integer
                               3593                 :                :      * result, so the LCM is an integral multiple of both x and y.  A display
                               3594                 :                :      * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
                               3595                 :                :      * but as with other numeric functions, we choose to return a result whose
                               3596                 :                :      * display scale is no smaller than either input.
                               3597                 :                :      */
                               3598   [ +  +  +  + ]:             75 :     if (arg1.ndigits == 0 || arg2.ndigits == 0)
                               3599                 :             24 :         set_var_from_var(&const_zero, &result);
                               3600                 :                :     else
                               3601                 :                :     {
                               3602                 :             51 :         gcd_var(&arg1, &arg2, &result);
                               3603                 :             51 :         div_var(&arg1, &result, &result, 0, false);
                               3604                 :             51 :         mul_var(&arg2, &result, &result, arg2.dscale);
                               3605                 :             51 :         result.sign = NUMERIC_POS;
                               3606                 :                :     }
                               3607                 :                : 
                               3608                 :             75 :     result.dscale = Max(arg1.dscale, arg2.dscale);
                               3609                 :                : 
                               3610                 :             75 :     res = make_result(&result);
                               3611                 :                : 
                               3612                 :             72 :     free_var(&result);
                               3613                 :                : 
                               3614                 :             72 :     PG_RETURN_NUMERIC(res);
                               3615                 :                : }
                               3616                 :                : 
                               3617                 :                : 
                               3618                 :                : /*
                               3619                 :                :  * numeric_fac()
                               3620                 :                :  *
                               3621                 :                :  * Compute factorial
                               3622                 :                :  */
                               3623                 :                : Datum
 7440 bruce@momjian.us         3624                 :             21 : numeric_fac(PG_FUNCTION_ARGS)
                               3625                 :                : {
                               3626                 :             21 :     int64       num = PG_GETARG_INT64(0);
                               3627                 :                :     Numeric     res;
                               3628                 :                :     NumericVar  fact;
                               3629                 :                :     NumericVar  result;
                               3630                 :                : 
 1396 peter@eisentraut.org     3631         [ +  + ]:             21 :     if (num < 0)
                               3632         [ +  - ]:              3 :         ereport(ERROR,
                               3633                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               3634                 :                :                  errmsg("factorial of a negative number is undefined")));
 7439 tgl@sss.pgh.pa.us        3635         [ +  + ]:             18 :     if (num <= 1)
                               3636                 :                :     {
 7440 bruce@momjian.us         3637                 :              3 :         res = make_result(&const_one);
                               3638                 :              3 :         PG_RETURN_NUMERIC(res);
                               3639                 :                :     }
                               3640                 :                :     /* Fail immediately if the result would overflow */
 6154 tgl@sss.pgh.pa.us        3641         [ +  + ]:             15 :     if (num > 32177)
                               3642         [ +  - ]:              3 :         ereport(ERROR,
                               3643                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               3644                 :                :                  errmsg("value overflows numeric format")));
                               3645                 :                : 
 7440 bruce@momjian.us         3646                 :             12 :     init_var(&fact);
                               3647                 :             12 :     init_var(&result);
                               3648                 :                : 
 3313 andres@anarazel.de       3649                 :             12 :     int64_to_numericvar(num, &result);
                               3650                 :                : 
 7439 tgl@sss.pgh.pa.us        3651         [ +  + ]:            147 :     for (num = num - 1; num > 1; num--)
                               3652                 :                :     {
                               3653                 :                :         /* this loop can take awhile, so allow it to be interrupted */
 6154                          3654         [ -  + ]:            135 :         CHECK_FOR_INTERRUPTS();
                               3655                 :                : 
 3313 andres@anarazel.de       3656                 :            135 :         int64_to_numericvar(num, &fact);
                               3657                 :                : 
 7439 tgl@sss.pgh.pa.us        3658                 :            135 :         mul_var(&result, &fact, &result, 0);
                               3659                 :                :     }
                               3660                 :                : 
                               3661                 :             12 :     res = make_result(&result);
                               3662                 :                : 
 7440 bruce@momjian.us         3663                 :             12 :     free_var(&fact);
                               3664                 :             12 :     free_var(&result);
                               3665                 :                : 
                               3666                 :             12 :     PG_RETURN_NUMERIC(res);
                               3667                 :                : }
                               3668                 :                : 
                               3669                 :                : 
                               3670                 :                : /*
                               3671                 :                :  * numeric_sqrt() -
                               3672                 :                :  *
                               3673                 :                :  *  Compute the square root of a numeric.
                               3674                 :                :  */
                               3675                 :                : Datum
 8660 tgl@sss.pgh.pa.us        3676                 :             75 : numeric_sqrt(PG_FUNCTION_ARGS)
                               3677                 :                : {
                               3678                 :             75 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3679                 :                :     Numeric     res;
                               3680                 :                :     NumericVar  arg;
                               3681                 :                :     NumericVar  result;
                               3682                 :                :     int         sweight;
                               3683                 :                :     int         rscale;
                               3684                 :                : 
                               3685                 :                :     /*
                               3686                 :                :      * Handle NaN and infinities
                               3687                 :                :      */
 1362                          3688         [ +  + ]:             75 :     if (NUMERIC_IS_SPECIAL(num))
                               3689                 :                :     {
                               3690                 :                :         /* error should match that in sqrt_var() */
                               3691         [ +  + ]:              9 :         if (NUMERIC_IS_NINF(num))
                               3692         [ +  - ]:              3 :             ereport(ERROR,
                               3693                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               3694                 :                :                      errmsg("cannot take square root of a negative number")));
                               3695                 :                :         /* For NAN or PINF, just duplicate the input */
                               3696                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3697                 :                :     }
                               3698                 :                : 
                               3699                 :                :     /*
                               3700                 :                :      * Unpack the argument and determine the result scale.  We choose a scale
                               3701                 :                :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
                               3702                 :                :      * case not less than the input's dscale.
                               3703                 :                :      */
 4162 heikki.linnakangas@i     3704                 :             66 :     init_var_from_num(num, &arg);
                               3705                 :                : 
                               3706                 :             66 :     init_var(&result);
                               3707                 :                : 
                               3708                 :                :     /*
                               3709                 :                :      * Assume the input was normalized, so arg.weight is accurate.  The result
                               3710                 :                :      * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
                               3711                 :                :      * digits before the decimal point.  When DEC_DIGITS is even, we can save
                               3712                 :                :      * a few cycles, since the division is exact and there is no need to round
                               3713                 :                :      * towards negative infinity.
                               3714                 :                :      */
                               3715                 :                : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
  437 dean.a.rasheed@gmail     3716                 :             66 :     sweight = arg.weight * DEC_DIGITS / 2 + 1;
                               3717                 :                : #else
                               3718                 :                :     if (arg.weight >= 0)
                               3719                 :                :         sweight = arg.weight * DEC_DIGITS / 2 + 1;
                               3720                 :                :     else
                               3721                 :                :         sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
                               3722                 :                : #endif
                               3723                 :                : 
 7695 tgl@sss.pgh.pa.us        3724                 :             66 :     rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
                               3725                 :             66 :     rscale = Max(rscale, arg.dscale);
                               3726                 :             66 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               3727                 :             66 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               3728                 :                : 
                               3729                 :                :     /*
                               3730                 :                :      * Let sqrt_var() do the calculation and return the result.
                               3731                 :                :      */
                               3732                 :             66 :     sqrt_var(&arg, &result, rscale);
                               3733                 :                : 
 9237 JanWieck@Yahoo.com       3734                 :             63 :     res = make_result(&result);
                               3735                 :                : 
                               3736                 :             63 :     free_var(&result);
                               3737                 :                : 
 8660 tgl@sss.pgh.pa.us        3738                 :             63 :     PG_RETURN_NUMERIC(res);
                               3739                 :                : }
                               3740                 :                : 
                               3741                 :                : 
                               3742                 :                : /*
                               3743                 :                :  * numeric_exp() -
                               3744                 :                :  *
                               3745                 :                :  *  Raise e to the power of x
                               3746                 :                :  */
                               3747                 :                : Datum
                               3748                 :             39 : numeric_exp(PG_FUNCTION_ARGS)
                               3749                 :                : {
                               3750                 :             39 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3751                 :                :     Numeric     res;
                               3752                 :                :     NumericVar  arg;
                               3753                 :                :     NumericVar  result;
                               3754                 :                :     int         rscale;
                               3755                 :                :     double      val;
                               3756                 :                : 
                               3757                 :                :     /*
                               3758                 :                :      * Handle NaN and infinities
                               3759                 :                :      */
 1362                          3760         [ +  + ]:             39 :     if (NUMERIC_IS_SPECIAL(num))
                               3761                 :                :     {
                               3762                 :                :         /* Per POSIX, exp(-Inf) is zero */
                               3763         [ +  + ]:              9 :         if (NUMERIC_IS_NINF(num))
                               3764                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               3765                 :                :         /* For NAN or PINF, just duplicate the input */
                               3766                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3767                 :                :     }
                               3768                 :                : 
                               3769                 :                :     /*
                               3770                 :                :      * Unpack the argument and determine the result scale.  We choose a scale
                               3771                 :                :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
                               3772                 :                :      * case not less than the input's dscale.
                               3773                 :                :      */
 4162 heikki.linnakangas@i     3774                 :             30 :     init_var_from_num(num, &arg);
                               3775                 :                : 
                               3776                 :             30 :     init_var(&result);
                               3777                 :                : 
                               3778                 :                :     /* convert input to float8, ignoring overflow */
 7695 tgl@sss.pgh.pa.us        3779                 :             30 :     val = numericvar_to_double_no_overflow(&arg);
                               3780                 :                : 
                               3781                 :                :     /*
                               3782                 :                :      * log10(result) = num * log10(e), so this is approximately the decimal
                               3783                 :                :      * weight of the result:
                               3784                 :                :      */
 7865                          3785                 :             30 :     val *= 0.434294481903252;
                               3786                 :                : 
                               3787                 :                :     /* limit to something that won't cause integer overflow */
                               3788         [ +  + ]:             30 :     val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
                               3789         [ +  - ]:             30 :     val = Min(val, NUMERIC_MAX_RESULT_SCALE);
                               3790                 :                : 
 7695                          3791                 :             30 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
                               3792                 :             30 :     rscale = Max(rscale, arg.dscale);
                               3793                 :             30 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               3794                 :             30 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               3795                 :                : 
                               3796                 :                :     /*
                               3797                 :                :      * Let exp_var() do the calculation and return the result.
                               3798                 :                :      */
                               3799                 :             30 :     exp_var(&arg, &result, rscale);
                               3800                 :                : 
 9237 JanWieck@Yahoo.com       3801                 :             30 :     res = make_result(&result);
                               3802                 :                : 
                               3803                 :             30 :     free_var(&result);
                               3804                 :                : 
 8660 tgl@sss.pgh.pa.us        3805                 :             30 :     PG_RETURN_NUMERIC(res);
                               3806                 :                : }
                               3807                 :                : 
                               3808                 :                : 
                               3809                 :                : /*
                               3810                 :                :  * numeric_ln() -
                               3811                 :                :  *
                               3812                 :                :  *  Compute the natural logarithm of x
                               3813                 :                :  */
                               3814                 :                : Datum
                               3815                 :             99 : numeric_ln(PG_FUNCTION_ARGS)
                               3816                 :                : {
                               3817                 :             99 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3818                 :                :     Numeric     res;
                               3819                 :                :     NumericVar  arg;
                               3820                 :                :     NumericVar  result;
                               3821                 :                :     int         ln_dweight;
                               3822                 :                :     int         rscale;
                               3823                 :                : 
                               3824                 :                :     /*
                               3825                 :                :      * Handle NaN and infinities
                               3826                 :                :      */
 1362                          3827         [ +  + ]:             99 :     if (NUMERIC_IS_SPECIAL(num))
                               3828                 :                :     {
                               3829         [ +  + ]:              9 :         if (NUMERIC_IS_NINF(num))
                               3830         [ +  - ]:              3 :             ereport(ERROR,
                               3831                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                               3832                 :                :                      errmsg("cannot take logarithm of a negative number")));
                               3833                 :                :         /* For NAN or PINF, just duplicate the input */
                               3834                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3835                 :                :     }
                               3836                 :                : 
 4162 heikki.linnakangas@i     3837                 :             90 :     init_var_from_num(num, &arg);
 9237 JanWieck@Yahoo.com       3838                 :             90 :     init_var(&result);
                               3839                 :                : 
                               3840                 :                :     /* Estimated dweight of logarithm */
 3074 tgl@sss.pgh.pa.us        3841                 :             90 :     ln_dweight = estimate_ln_dweight(&arg);
                               3842                 :                : 
                               3843                 :             90 :     rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
 7695                          3844                 :             90 :     rscale = Max(rscale, arg.dscale);
                               3845                 :             90 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               3846                 :             90 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               3847                 :                : 
                               3848                 :             90 :     ln_var(&arg, &result, rscale);
                               3849                 :                : 
 9237 JanWieck@Yahoo.com       3850                 :             78 :     res = make_result(&result);
                               3851                 :                : 
                               3852                 :             78 :     free_var(&result);
                               3853                 :                : 
 8660 tgl@sss.pgh.pa.us        3854                 :             78 :     PG_RETURN_NUMERIC(res);
                               3855                 :                : }
                               3856                 :                : 
                               3857                 :                : 
                               3858                 :                : /*
                               3859                 :                :  * numeric_log() -
                               3860                 :                :  *
                               3861                 :                :  *  Compute the logarithm of x in a given base
                               3862                 :                :  */
                               3863                 :                : Datum
                               3864                 :            171 : numeric_log(PG_FUNCTION_ARGS)
                               3865                 :                : {
                               3866                 :            171 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3867                 :            171 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3868                 :                :     Numeric     res;
                               3869                 :                :     NumericVar  arg1;
                               3870                 :                :     NumericVar  arg2;
                               3871                 :                :     NumericVar  result;
                               3872                 :                : 
                               3873                 :                :     /*
                               3874                 :                :      * Handle NaN and infinities
                               3875                 :                :      */
 1362                          3876   [ +  +  +  + ]:            171 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3877                 :                :     {
                               3878                 :                :         int         sign1,
                               3879                 :                :                     sign2;
                               3880                 :                : 
                               3881   [ +  +  +  + ]:             63 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3882                 :             27 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3883                 :                :         /* fail on negative inputs including -Inf, as log_var would */
                               3884                 :             36 :         sign1 = numeric_sign_internal(num1);
                               3885                 :             36 :         sign2 = numeric_sign_internal(num2);
                               3886   [ +  +  +  + ]:             36 :         if (sign1 < 0 || sign2 < 0)
                               3887         [ +  - ]:             12 :             ereport(ERROR,
                               3888                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                               3889                 :                :                      errmsg("cannot take logarithm of a negative number")));
                               3890                 :                :         /* fail on zero inputs, as log_var would */
                               3891   [ +  -  +  + ]:             24 :         if (sign1 == 0 || sign2 == 0)
                               3892         [ +  - ]:              3 :             ereport(ERROR,
                               3893                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                               3894                 :                :                      errmsg("cannot take logarithm of zero")));
                               3895         [ +  + ]:             21 :         if (NUMERIC_IS_PINF(num1))
                               3896                 :                :         {
                               3897                 :                :             /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
                               3898         [ +  + ]:              9 :             if (NUMERIC_IS_PINF(num2))
                               3899                 :              3 :                 PG_RETURN_NUMERIC(make_result(&const_nan));
                               3900                 :                :             /* log(Inf, finite-positive) is zero (we don't throw underflow) */
                               3901                 :              6 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               3902                 :                :         }
                               3903         [ -  + ]:             12 :         Assert(NUMERIC_IS_PINF(num2));
                               3904                 :                :         /* log(finite-positive, Inf) is Inf */
                               3905                 :             12 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
                               3906                 :                :     }
                               3907                 :                : 
                               3908                 :                :     /*
                               3909                 :                :      * Initialize things
                               3910                 :                :      */
 4162 heikki.linnakangas@i     3911                 :            108 :     init_var_from_num(num1, &arg1);
                               3912                 :            108 :     init_var_from_num(num2, &arg2);
 9237 JanWieck@Yahoo.com       3913                 :            108 :     init_var(&result);
                               3914                 :                : 
                               3915                 :                :     /*
                               3916                 :                :      * Call log_var() to compute and return the result; note it handles scale
                               3917                 :                :      * selection itself.
                               3918                 :                :      */
                               3919                 :            108 :     log_var(&arg1, &arg2, &result);
                               3920                 :                : 
                               3921                 :             78 :     res = make_result(&result);
                               3922                 :                : 
                               3923                 :             78 :     free_var(&result);
                               3924                 :                : 
 8660 tgl@sss.pgh.pa.us        3925                 :             78 :     PG_RETURN_NUMERIC(res);
                               3926                 :                : }
                               3927                 :                : 
                               3928                 :                : 
                               3929                 :                : /*
                               3930                 :                :  * numeric_power() -
                               3931                 :                :  *
                               3932                 :                :  *  Raise x to the power of y
                               3933                 :                :  */
                               3934                 :                : Datum
                               3935                 :            816 : numeric_power(PG_FUNCTION_ARGS)
                               3936                 :                : {
                               3937                 :            816 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3938                 :            816 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3939                 :                :     Numeric     res;
                               3940                 :                :     NumericVar  arg1;
                               3941                 :                :     NumericVar  arg2;
                               3942                 :                :     NumericVar  result;
                               3943                 :                :     int         sign1,
                               3944                 :                :                 sign2;
                               3945                 :                : 
                               3946                 :                :     /*
                               3947                 :                :      * Handle NaN and infinities
                               3948                 :                :      */
 1362                          3949   [ +  +  +  + ]:            816 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3950                 :                :     {
                               3951                 :                :         /*
                               3952                 :                :          * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
                               3953                 :                :          * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
                               3954                 :                :          * (with no error).
                               3955                 :                :          */
                               3956         [ +  + ]:            117 :         if (NUMERIC_IS_NAN(num1))
                               3957                 :                :         {
                               3958         [ +  + ]:             27 :             if (!NUMERIC_IS_SPECIAL(num2))
                               3959                 :                :             {
                               3960                 :             18 :                 init_var_from_num(num2, &arg2);
                               3961         [ +  + ]:             18 :                 if (cmp_var(&arg2, &const_zero) == 0)
                               3962                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_one));
                               3963                 :                :             }
                               3964                 :             21 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3965                 :                :         }
                               3966         [ +  + ]:             90 :         if (NUMERIC_IS_NAN(num2))
                               3967                 :                :         {
                               3968         [ +  + ]:             21 :             if (!NUMERIC_IS_SPECIAL(num1))
                               3969                 :                :             {
                               3970                 :             18 :                 init_var_from_num(num1, &arg1);
                               3971         [ +  + ]:             18 :                 if (cmp_var(&arg1, &const_one) == 0)
                               3972                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_one));
                               3973                 :                :             }
                               3974                 :             15 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3975                 :                :         }
                               3976                 :                :         /* At least one input is infinite, but error rules still apply */
                               3977                 :             69 :         sign1 = numeric_sign_internal(num1);
                               3978                 :             69 :         sign2 = numeric_sign_internal(num2);
                               3979   [ +  +  +  + ]:             69 :         if (sign1 == 0 && sign2 < 0)
                               3980         [ +  - ]:              3 :             ereport(ERROR,
                               3981                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               3982                 :                :                      errmsg("zero raised to a negative power is undefined")));
                               3983   [ +  +  +  + ]:             66 :         if (sign1 < 0 && !numeric_is_integral(num2))
                               3984         [ +  - ]:              3 :             ereport(ERROR,
                               3985                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               3986                 :                :                      errmsg("a negative number raised to a non-integer power yields a complex result")));
                               3987                 :                : 
                               3988                 :                :         /*
                               3989                 :                :          * POSIX gives this series of rules for pow(3) with infinite inputs:
                               3990                 :                :          *
                               3991                 :                :          * For any value of y, if x is +1, 1.0 shall be returned.
                               3992                 :                :          */
                               3993         [ +  + ]:             63 :         if (!NUMERIC_IS_SPECIAL(num1))
                               3994                 :                :         {
                               3995                 :             21 :             init_var_from_num(num1, &arg1);
                               3996         [ +  + ]:             21 :             if (cmp_var(&arg1, &const_one) == 0)
 2159                          3997                 :              3 :                 PG_RETURN_NUMERIC(make_result(&const_one));
                               3998                 :                :         }
                               3999                 :                : 
                               4000                 :                :         /*
                               4001                 :                :          * For any value of x, if y is [-]0, 1.0 shall be returned.
                               4002                 :                :          */
 1362                          4003         [ +  + ]:             60 :         if (sign2 == 0)
 2159                          4004                 :              6 :             PG_RETURN_NUMERIC(make_result(&const_one));
                               4005                 :                : 
                               4006                 :                :         /*
                               4007                 :                :          * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
                               4008                 :                :          * returned.  For y > 0 and not an odd integer, if x is [-]0, +0 shall
                               4009                 :                :          * be returned.  (Since we don't deal in minus zero, we need not
                               4010                 :                :          * distinguish these two cases.)
                               4011                 :                :          */
 1362                          4012   [ +  +  +  - ]:             54 :         if (sign1 == 0 && sign2 > 0)
                               4013                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               4014                 :                : 
                               4015                 :                :         /*
                               4016                 :                :          * If x is -1, and y is [-]Inf, 1.0 shall be returned.
                               4017                 :                :          *
                               4018                 :                :          * For |x| < 1, if y is -Inf, +Inf shall be returned.
                               4019                 :                :          *
                               4020                 :                :          * For |x| > 1, if y is -Inf, +0 shall be returned.
                               4021                 :                :          *
                               4022                 :                :          * For |x| < 1, if y is +Inf, +0 shall be returned.
                               4023                 :                :          *
                               4024                 :                :          * For |x| > 1, if y is +Inf, +Inf shall be returned.
                               4025                 :                :          */
                               4026         [ +  + ]:             51 :         if (NUMERIC_IS_INF(num2))
                               4027                 :                :         {
                               4028                 :                :             bool        abs_x_gt_one;
                               4029                 :                : 
                               4030         [ +  + ]:             27 :             if (NUMERIC_IS_SPECIAL(num1))
                               4031                 :             12 :                 abs_x_gt_one = true;    /* x is either Inf or -Inf */
                               4032                 :                :             else
                               4033                 :                :             {
                               4034                 :             15 :                 init_var_from_num(num1, &arg1);
                               4035         [ +  + ]:             15 :                 if (cmp_var(&arg1, &const_minus_one) == 0)
                               4036                 :              3 :                     PG_RETURN_NUMERIC(make_result(&const_one));
                               4037                 :             12 :                 arg1.sign = NUMERIC_POS;    /* now arg1 = abs(x) */
                               4038                 :             12 :                 abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
                               4039                 :                :             }
                               4040         [ +  + ]:             24 :             if (abs_x_gt_one == (sign2 > 0))
                               4041                 :             15 :                 PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4042                 :                :             else
                               4043                 :              9 :                 PG_RETURN_NUMERIC(make_result(&const_zero));
                               4044                 :                :         }
                               4045                 :                : 
                               4046                 :                :         /*
                               4047                 :                :          * For y < 0, if x is +Inf, +0 shall be returned.
                               4048                 :                :          *
                               4049                 :                :          * For y > 0, if x is +Inf, +Inf shall be returned.
                               4050                 :                :          */
                               4051         [ +  + ]:             24 :         if (NUMERIC_IS_PINF(num1))
                               4052                 :                :         {
                               4053         [ +  + ]:             12 :             if (sign2 > 0)
                               4054                 :              9 :                 PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4055                 :                :             else
                               4056                 :              3 :                 PG_RETURN_NUMERIC(make_result(&const_zero));
                               4057                 :                :         }
                               4058                 :                : 
                               4059         [ -  + ]:             12 :         Assert(NUMERIC_IS_NINF(num1));
                               4060                 :                : 
                               4061                 :                :         /*
                               4062                 :                :          * For y an odd integer < 0, if x is -Inf, -0 shall be returned.  For
                               4063                 :                :          * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
                               4064                 :                :          * (Again, we need not distinguish these two cases.)
                               4065                 :                :          */
                               4066         [ +  + ]:             12 :         if (sign2 < 0)
                               4067                 :              6 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               4068                 :                : 
                               4069                 :                :         /*
                               4070                 :                :          * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
                               4071                 :                :          * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
                               4072                 :                :          */
                               4073                 :              6 :         init_var_from_num(num2, &arg2);
                               4074   [ +  -  +  - ]:              6 :         if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
                               4075         [ +  + ]:              6 :             (arg2.digits[arg2.ndigits - 1] & 1))
                               4076                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
                               4077                 :                :         else
                               4078                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4079                 :                :     }
                               4080                 :                : 
                               4081                 :                :     /*
                               4082                 :                :      * The SQL spec requires that we emit a particular SQLSTATE error code for
                               4083                 :                :      * certain error conditions.  Specifically, we don't return a
                               4084                 :                :      * divide-by-zero error code for 0 ^ -1.  Raising a negative number to a
                               4085                 :                :      * non-integer power must produce the same error code, but that case is
                               4086                 :                :      * handled in power_var().
                               4087                 :                :      */
                               4088                 :            699 :     sign1 = numeric_sign_internal(num1);
                               4089                 :            699 :     sign2 = numeric_sign_internal(num2);
                               4090                 :                : 
                               4091   [ +  +  +  + ]:            699 :     if (sign1 == 0 && sign2 < 0)
 7273 neilc@samurai.com        4092         [ +  - ]:              6 :         ereport(ERROR,
                               4093                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               4094                 :                :                  errmsg("zero raised to a negative power is undefined")));
                               4095                 :                : 
                               4096                 :                :     /*
                               4097                 :                :      * Initialize things
                               4098                 :                :      */
 1362 tgl@sss.pgh.pa.us        4099                 :            693 :     init_var(&result);
                               4100                 :            693 :     init_var_from_num(num1, &arg1);
                               4101                 :            693 :     init_var_from_num(num2, &arg2);
                               4102                 :                : 
                               4103                 :                :     /*
                               4104                 :                :      * Call power_var() to compute and return the result; note it handles
                               4105                 :                :      * scale selection itself.
                               4106                 :                :      */
 9237 JanWieck@Yahoo.com       4107                 :            693 :     power_var(&arg1, &arg2, &result);
                               4108                 :                : 
                               4109                 :            678 :     res = make_result(&result);
                               4110                 :                : 
                               4111                 :            678 :     free_var(&result);
                               4112                 :                : 
 8660 tgl@sss.pgh.pa.us        4113                 :            678 :     PG_RETURN_NUMERIC(res);
                               4114                 :                : }
                               4115                 :                : 
                               4116                 :                : /*
                               4117                 :                :  * numeric_scale() -
                               4118                 :                :  *
                               4119                 :                :  *  Returns the scale, i.e. the count of decimal digits in the fractional part
                               4120                 :                :  */
                               4121                 :                : Datum
 3022 alvherre@alvh.no-ip.     4122                 :             54 : numeric_scale(PG_FUNCTION_ARGS)
                               4123                 :                : {
                               4124                 :             54 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4125                 :                : 
 1362 tgl@sss.pgh.pa.us        4126         [ +  + ]:             54 :     if (NUMERIC_IS_SPECIAL(num))
 3022 alvherre@alvh.no-ip.     4127                 :              9 :         PG_RETURN_NULL();
                               4128                 :                : 
                               4129         [ +  - ]:             45 :     PG_RETURN_INT32(NUMERIC_DSCALE(num));
                               4130                 :                : }
                               4131                 :                : 
                               4132                 :                : /*
                               4133                 :                :  * Calculate minimum scale for value.
                               4134                 :                :  */
                               4135                 :                : static int
 1560 tgl@sss.pgh.pa.us        4136                 :            186 : get_min_scale(NumericVar *var)
                               4137                 :                : {
                               4138                 :                :     int         min_scale;
                               4139                 :                :     int         last_digit_pos;
                               4140                 :                : 
                               4141                 :                :     /*
                               4142                 :                :      * Ordinarily, the input value will be "stripped" so that the last
                               4143                 :                :      * NumericDigit is nonzero.  But we don't want to get into an infinite
                               4144                 :                :      * loop if it isn't, so explicitly find the last nonzero digit.
                               4145                 :                :      */
                               4146                 :            186 :     last_digit_pos = var->ndigits - 1;
                               4147         [ +  + ]:            186 :     while (last_digit_pos >= 0 &&
                               4148         [ -  + ]:            171 :            var->digits[last_digit_pos] == 0)
 1560 tgl@sss.pgh.pa.us        4149                 :UBC           0 :         last_digit_pos--;
                               4150                 :                : 
 1560 tgl@sss.pgh.pa.us        4151         [ +  + ]:CBC         186 :     if (last_digit_pos >= 0)
                               4152                 :                :     {
                               4153                 :                :         /* compute min_scale assuming that last ndigit has no zeroes */
                               4154                 :            171 :         min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
                               4155                 :                : 
                               4156                 :                :         /*
                               4157                 :                :          * We could get a negative result if there are no digits after the
                               4158                 :                :          * decimal point.  In this case the min_scale must be zero.
                               4159                 :                :          */
                               4160         [ +  + ]:            171 :         if (min_scale > 0)
                               4161                 :                :         {
                               4162                 :                :             /*
                               4163                 :                :              * Reduce min_scale if trailing digit(s) in last NumericDigit are
                               4164                 :                :              * zero.
                               4165                 :                :              */
                               4166                 :             93 :             NumericDigit last_digit = var->digits[last_digit_pos];
                               4167                 :                : 
                               4168         [ +  + ]:            249 :             while (last_digit % 10 == 0)
                               4169                 :                :             {
                               4170                 :            156 :                 min_scale--;
                               4171                 :            156 :                 last_digit /= 10;
                               4172                 :                :             }
                               4173                 :                :         }
                               4174                 :                :         else
                               4175                 :             78 :             min_scale = 0;
                               4176                 :                :     }
                               4177                 :                :     else
                               4178                 :             15 :         min_scale = 0;          /* result if input is zero */
                               4179                 :                : 
                               4180                 :            186 :     return min_scale;
                               4181                 :                : }
                               4182                 :                : 
                               4183                 :                : /*
                               4184                 :                :  * Returns minimum scale required to represent supplied value without loss.
                               4185                 :                :  */
                               4186                 :                : Datum
                               4187                 :             36 : numeric_min_scale(PG_FUNCTION_ARGS)
                               4188                 :                : {
                               4189                 :             36 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4190                 :                :     NumericVar  arg;
                               4191                 :                :     int         min_scale;
                               4192                 :                : 
 1362                          4193         [ +  + ]:             36 :     if (NUMERIC_IS_SPECIAL(num))
 1560                          4194                 :              6 :         PG_RETURN_NULL();
                               4195                 :                : 
                               4196                 :             30 :     init_var_from_num(num, &arg);
                               4197                 :             30 :     min_scale = get_min_scale(&arg);
                               4198                 :             30 :     free_var(&arg);
                               4199                 :                : 
                               4200                 :             30 :     PG_RETURN_INT32(min_scale);
                               4201                 :                : }
                               4202                 :                : 
                               4203                 :                : /*
                               4204                 :                :  * Reduce scale of numeric value to represent supplied value without loss.
                               4205                 :                :  */
                               4206                 :                : Datum
                               4207                 :            162 : numeric_trim_scale(PG_FUNCTION_ARGS)
                               4208                 :                : {
                               4209                 :            162 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4210                 :                :     Numeric     res;
                               4211                 :                :     NumericVar  result;
                               4212                 :                : 
 1362                          4213         [ +  + ]:            162 :     if (NUMERIC_IS_SPECIAL(num))
                               4214                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               4215                 :                : 
 1560                          4216                 :            156 :     init_var_from_num(num, &result);
                               4217                 :            156 :     result.dscale = get_min_scale(&result);
                               4218                 :            156 :     res = make_result(&result);
                               4219                 :            156 :     free_var(&result);
                               4220                 :                : 
                               4221                 :            156 :     PG_RETURN_NUMERIC(res);
                               4222                 :                : }
                               4223                 :                : 
                               4224                 :                : /*
                               4225                 :                :  * Return a random numeric value in the range [rmin, rmax].
                               4226                 :                :  */
                               4227                 :                : Numeric
   18 dean.a.rasheed@gmail     4228                 :GNC       16731 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
                               4229                 :                : {
                               4230                 :                :     NumericVar  rmin_var;
                               4231                 :                :     NumericVar  rmax_var;
                               4232                 :                :     NumericVar  result;
                               4233                 :                :     Numeric     res;
                               4234                 :                : 
                               4235                 :                :     /* Range bounds must not be NaN/infinity */
                               4236         [ +  + ]:          16731 :     if (NUMERIC_IS_SPECIAL(rmin))
                               4237                 :                :     {
                               4238         [ +  + ]:              6 :         if (NUMERIC_IS_NAN(rmin))
                               4239         [ +  - ]:              3 :             ereport(ERROR,
                               4240                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4241                 :                :                     errmsg("lower bound cannot be NaN"));
                               4242                 :                :         else
                               4243         [ +  - ]:              3 :             ereport(ERROR,
                               4244                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4245                 :                :                     errmsg("lower bound cannot be infinity"));
                               4246                 :                :     }
                               4247         [ +  + ]:          16725 :     if (NUMERIC_IS_SPECIAL(rmax))
                               4248                 :                :     {
                               4249         [ +  + ]:              6 :         if (NUMERIC_IS_NAN(rmax))
                               4250         [ +  - ]:              3 :             ereport(ERROR,
                               4251                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4252                 :                :                     errmsg("upper bound cannot be NaN"));
                               4253                 :                :         else
                               4254         [ +  - ]:              3 :             ereport(ERROR,
                               4255                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4256                 :                :                     errmsg("upper bound cannot be infinity"));
                               4257                 :                :     }
                               4258                 :                : 
                               4259                 :                :     /* Return a random value in the range [rmin, rmax] */
                               4260                 :          16719 :     init_var_from_num(rmin, &rmin_var);
                               4261                 :          16719 :     init_var_from_num(rmax, &rmax_var);
                               4262                 :                : 
                               4263                 :          16719 :     init_var(&result);
                               4264                 :                : 
                               4265                 :          16719 :     random_var(state, &rmin_var, &rmax_var, &result);
                               4266                 :                : 
                               4267                 :          16716 :     res = make_result(&result);
                               4268                 :                : 
                               4269                 :          16716 :     free_var(&result);
                               4270                 :                : 
                               4271                 :          16716 :     return res;
                               4272                 :                : }
                               4273                 :                : 
                               4274                 :                : 
                               4275                 :                : /* ----------------------------------------------------------------------
                               4276                 :                :  *
                               4277                 :                :  * Type conversion functions
                               4278                 :                :  *
                               4279                 :                :  * ----------------------------------------------------------------------
                               4280                 :                :  */
                               4281                 :                : 
                               4282                 :                : Numeric
 1313 peter@eisentraut.org     4283                 :CBC      924860 : int64_to_numeric(int64 val)
                               4284                 :                : {
                               4285                 :                :     Numeric     res;
                               4286                 :                :     NumericVar  result;
                               4287                 :                : 
 9237 JanWieck@Yahoo.com       4288                 :         924860 :     init_var(&result);
                               4289                 :                : 
 1313 peter@eisentraut.org     4290                 :         924860 :     int64_to_numericvar(val, &result);
                               4291                 :                : 
 9237 JanWieck@Yahoo.com       4292                 :         924860 :     res = make_result(&result);
                               4293                 :                : 
                               4294                 :         924860 :     free_var(&result);
                               4295                 :                : 
 1313 peter@eisentraut.org     4296                 :         924860 :     return res;
                               4297                 :                : }
                               4298                 :                : 
                               4299                 :                : /*
                               4300                 :                :  * Convert val1/(10**log10val2) to numeric.  This is much faster than normal
                               4301                 :                :  * numeric division.
                               4302                 :                :  */
                               4303                 :                : Numeric
 1104                          4304                 :          14604 : int64_div_fast_to_numeric(int64 val1, int log10val2)
                               4305                 :                : {
                               4306                 :                :     Numeric     res;
                               4307                 :                :     NumericVar  result;
                               4308                 :                :     int         rscale;
                               4309                 :                :     int         w;
                               4310                 :                :     int         m;
                               4311                 :                : 
  436 dean.a.rasheed@gmail     4312                 :          14604 :     init_var(&result);
                               4313                 :                : 
                               4314                 :                :     /* result scale */
                               4315                 :          14604 :     rscale = log10val2 < 0 ? 0 : log10val2;
                               4316                 :                : 
                               4317                 :                :     /* how much to decrease the weight by */
 1104 peter@eisentraut.org     4318                 :          14604 :     w = log10val2 / DEC_DIGITS;
                               4319                 :                :     /* how much is left to divide by */
                               4320                 :          14604 :     m = log10val2 % DEC_DIGITS;
  436 dean.a.rasheed@gmail     4321         [ -  + ]:          14604 :     if (m < 0)
                               4322                 :                :     {
  436 dean.a.rasheed@gmail     4323                 :UBC           0 :         m += DEC_DIGITS;
                               4324                 :              0 :         w--;
                               4325                 :                :     }
                               4326                 :                : 
                               4327                 :                :     /*
                               4328                 :                :      * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
                               4329                 :                :      * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
                               4330                 :                :      * one more.
                               4331                 :                :      */
 1104 peter@eisentraut.org     4332         [ +  - ]:CBC       14604 :     if (m > 0)
                               4333                 :                :     {
                               4334                 :                : #if DEC_DIGITS == 4
                               4335                 :                :         static const int pow10[] = {1, 10, 100, 1000};
                               4336                 :                : #elif DEC_DIGITS == 2
                               4337                 :                :         static const int pow10[] = {1, 10};
                               4338                 :                : #elif DEC_DIGITS == 1
                               4339                 :                :         static const int pow10[] = {1};
                               4340                 :                : #else
                               4341                 :                : #error unsupported NBASE
                               4342                 :                : #endif
  436 dean.a.rasheed@gmail     4343                 :          14604 :         int64       factor = pow10[DEC_DIGITS - m];
                               4344                 :                :         int64       new_val1;
                               4345                 :                : 
                               4346                 :                :         StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
                               4347                 :                : 
                               4348         [ +  + ]:          14604 :         if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
                               4349                 :                :         {
                               4350                 :                : #ifdef HAVE_INT128
                               4351                 :                :             /* do the multiplication using 128-bit integers */
                               4352                 :                :             int128      tmp;
                               4353                 :                : 
                               4354                 :              6 :             tmp = (int128) val1 * (int128) factor;
                               4355                 :                : 
                               4356                 :              6 :             int128_to_numericvar(tmp, &result);
                               4357                 :                : #else
                               4358                 :                :             /* do the multiplication using numerics */
                               4359                 :                :             NumericVar  tmp;
                               4360                 :                : 
                               4361                 :                :             init_var(&tmp);
                               4362                 :                : 
                               4363                 :                :             int64_to_numericvar(val1, &result);
                               4364                 :                :             int64_to_numericvar(factor, &tmp);
                               4365                 :                :             mul_var(&result, &tmp, &result, 0);
                               4366                 :                : 
                               4367                 :                :             free_var(&tmp);
                               4368                 :                : #endif
                               4369                 :                :         }
                               4370                 :                :         else
                               4371                 :          14598 :             int64_to_numericvar(new_val1, &result);
                               4372                 :                : 
 1104 peter@eisentraut.org     4373                 :          14604 :         w++;
                               4374                 :                :     }
                               4375                 :                :     else
  436 dean.a.rasheed@gmail     4376                 :UBC           0 :         int64_to_numericvar(val1, &result);
                               4377                 :                : 
 1104 peter@eisentraut.org     4378                 :CBC       14604 :     result.weight -= w;
  436 dean.a.rasheed@gmail     4379                 :          14604 :     result.dscale = rscale;
                               4380                 :                : 
 1104 peter@eisentraut.org     4381                 :          14604 :     res = make_result(&result);
                               4382                 :                : 
                               4383                 :          14604 :     free_var(&result);
                               4384                 :                : 
                               4385                 :          14604 :     return res;
                               4386                 :                : }
                               4387                 :                : 
                               4388                 :                : Datum
 1313                          4389                 :         766161 : int4_numeric(PG_FUNCTION_ARGS)
                               4390                 :                : {
                               4391                 :         766161 :     int32       val = PG_GETARG_INT32(0);
                               4392                 :                : 
                               4393                 :         766161 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
                               4394                 :                : }
                               4395                 :                : 
                               4396                 :                : int32
 1856 akorotkov@postgresql     4397                 :           4197 : numeric_int4_opt_error(Numeric num, bool *have_error)
                               4398                 :                : {
                               4399                 :                :     NumericVar  x;
                               4400                 :                :     int32       result;
                               4401                 :                : 
 1714 michael@paquier.xyz      4402         [ +  + ]:           4197 :     if (have_error)
                               4403                 :            750 :         *have_error = false;
                               4404                 :                : 
 1362 tgl@sss.pgh.pa.us        4405         [ +  + ]:           4197 :     if (NUMERIC_IS_SPECIAL(num))
                               4406                 :                :     {
 1856 akorotkov@postgresql     4407         [ -  + ]:              9 :         if (have_error)
                               4408                 :                :         {
 1856 akorotkov@postgresql     4409                 :UBC           0 :             *have_error = true;
                               4410                 :              0 :             return 0;
                               4411                 :                :         }
                               4412                 :                :         else
                               4413                 :                :         {
 1362 tgl@sss.pgh.pa.us        4414         [ +  + ]:CBC           9 :             if (NUMERIC_IS_NAN(num))
                               4415         [ +  - ]:              3 :                 ereport(ERROR,
                               4416                 :                :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4417                 :                :                          errmsg("cannot convert NaN to %s", "integer")));
                               4418                 :                :             else
                               4419         [ +  - ]:              6 :                 ereport(ERROR,
                               4420                 :                :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4421                 :                :                          errmsg("cannot convert infinity to %s", "integer")));
                               4422                 :                :         }
                               4423                 :                :     }
                               4424                 :                : 
                               4425                 :                :     /* Convert to variable format, then convert to int4 */
 4162 heikki.linnakangas@i     4426                 :           4188 :     init_var_from_num(num, &x);
                               4427                 :                : 
 1856 akorotkov@postgresql     4428         [ +  + ]:           4188 :     if (!numericvar_to_int32(&x, &result))
                               4429                 :                :     {
                               4430         [ +  + ]:             42 :         if (have_error)
                               4431                 :                :         {
                               4432                 :             36 :             *have_error = true;
                               4433                 :             36 :             return 0;
                               4434                 :                :         }
                               4435                 :                :         else
                               4436                 :                :         {
                               4437         [ +  - ]:              6 :             ereport(ERROR,
                               4438                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4439                 :                :                      errmsg("integer out of range")));
                               4440                 :                :         }
                               4441                 :                :     }
                               4442                 :                : 
                               4443                 :           4146 :     return result;
                               4444                 :                : }
                               4445                 :                : 
                               4446                 :                : Datum
                               4447                 :           3447 : numeric_int4(PG_FUNCTION_ARGS)
                               4448                 :                : {
                               4449                 :           3447 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4450                 :                : 
                               4451                 :           3447 :     PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
                               4452                 :                : }
                               4453                 :                : 
                               4454                 :                : /*
                               4455                 :                :  * Given a NumericVar, convert it to an int32. If the NumericVar
                               4456                 :                :  * exceeds the range of an int32, false is returned, otherwise true is returned.
                               4457                 :                :  * The input NumericVar is *not* free'd.
                               4458                 :                :  */
                               4459                 :                : static bool
                               4460                 :           4557 : numericvar_to_int32(const NumericVar *var, int32 *result)
                               4461                 :                : {
                               4462                 :                :     int64       val;
                               4463                 :                : 
 3313 andres@anarazel.de       4464         [ +  + ]:           4557 :     if (!numericvar_to_int64(var, &val))
 1856 akorotkov@postgresql     4465                 :GBC           3 :         return false;
                               4466                 :                : 
  982 dean.a.rasheed@gmail     4467   [ +  +  +  + ]:CBC        4554 :     if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
                               4468                 :             39 :         return false;
                               4469                 :                : 
                               4470                 :                :     /* Down-convert to int4 */
 1856 akorotkov@postgresql     4471                 :           4515 :     *result = (int32) val;
                               4472                 :                : 
  982 dean.a.rasheed@gmail     4473                 :           4515 :     return true;
                               4474                 :                : }
                               4475                 :                : 
                               4476                 :                : Datum
 8672 tgl@sss.pgh.pa.us        4477                 :          18412 : int8_numeric(PG_FUNCTION_ARGS)
                               4478                 :                : {
 7695                          4479                 :          18412 :     int64       val = PG_GETARG_INT64(0);
                               4480                 :                : 
 1313 peter@eisentraut.org     4481                 :          18412 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
                               4482                 :                : }
                               4483                 :                : 
                               4484                 :                : int64
  102 peter@eisentraut.org     4485                 :GNC         282 : numeric_int8_opt_error(Numeric num, bool *have_error)
                               4486                 :                : {
                               4487                 :                :     NumericVar  x;
                               4488                 :                :     int64       result;
                               4489                 :                : 
                               4490         [ +  + ]:            282 :     if (have_error)
                               4491                 :             24 :         *have_error = false;
                               4492                 :                : 
 1362 tgl@sss.pgh.pa.us        4493         [ +  + ]:            282 :     if (NUMERIC_IS_SPECIAL(num))
                               4494                 :                :     {
  102 peter@eisentraut.org     4495         [ -  + ]:              9 :         if (have_error)
                               4496                 :                :         {
  102 peter@eisentraut.org     4497                 :UNC           0 :             *have_error = true;
                               4498                 :              0 :             return 0;
                               4499                 :                :         }
                               4500                 :                :         else
                               4501                 :                :         {
  102 peter@eisentraut.org     4502         [ +  + ]:GNC           9 :             if (NUMERIC_IS_NAN(num))
                               4503         [ +  - ]:              3 :                 ereport(ERROR,
                               4504                 :                :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4505                 :                :                          errmsg("cannot convert NaN to %s", "bigint")));
                               4506                 :                :             else
                               4507         [ +  - ]:              6 :                 ereport(ERROR,
                               4508                 :                :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4509                 :                :                          errmsg("cannot convert infinity to %s", "bigint")));
                               4510                 :                :         }
                               4511                 :                :     }
                               4512                 :                : 
                               4513                 :                :     /* Convert to variable format, then convert to int8 */
 4162 heikki.linnakangas@i     4514                 :            273 :     init_var_from_num(num, &x);
                               4515                 :                : 
 3313 andres@anarazel.de       4516         [ +  + ]:            273 :     if (!numericvar_to_int64(&x, &result))
                               4517                 :                :     {
  102 peter@eisentraut.org     4518         [ +  + ]:             30 :         if (have_error)
                               4519                 :                :         {
                               4520                 :              6 :             *have_error = true;
                               4521                 :              6 :             return 0;
                               4522                 :                :         }
                               4523                 :                :         else
                               4524                 :                :         {
                               4525         [ +  - ]:             24 :             ereport(ERROR,
                               4526                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4527                 :                :                      errmsg("bigint out of range")));
                               4528                 :                :         }
                               4529                 :                :     }
                               4530                 :                : 
                               4531                 :            243 :     return result;
                               4532                 :                : }
                               4533                 :                : 
                               4534                 :                : Datum
  102 peter@eisentraut.org     4535                 :CBC         258 : numeric_int8(PG_FUNCTION_ARGS)
                               4536                 :                : {
                               4537                 :            258 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4538                 :                : 
  102 peter@eisentraut.org     4539                 :GNC         258 :     PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
                               4540                 :                : }
                               4541                 :                : 
                               4542                 :                : 
                               4543                 :                : Datum
 8714 tgl@sss.pgh.pa.us        4544                 :CBC           3 : int2_numeric(PG_FUNCTION_ARGS)
                               4545                 :                : {
                               4546                 :              3 :     int16       val = PG_GETARG_INT16(0);
                               4547                 :                : 
 1313 peter@eisentraut.org     4548                 :              3 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
                               4549                 :                : }
                               4550                 :                : 
                               4551                 :                : 
                               4552                 :                : Datum
 8714 tgl@sss.pgh.pa.us        4553                 :             48 : numeric_int2(PG_FUNCTION_ARGS)
                               4554                 :                : {
                               4555                 :             48 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4556                 :                :     NumericVar  x;
                               4557                 :                :     int64       val;
                               4558                 :                :     int16       result;
                               4559                 :                : 
 1362                          4560         [ +  + ]:             48 :     if (NUMERIC_IS_SPECIAL(num))
                               4561                 :                :     {
                               4562         [ +  + ]:              9 :         if (NUMERIC_IS_NAN(num))
                               4563         [ +  - ]:              3 :             ereport(ERROR,
                               4564                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4565                 :                :                      errmsg("cannot convert NaN to %s", "smallint")));
                               4566                 :                :         else
                               4567         [ +  - ]:              6 :             ereport(ERROR,
                               4568                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4569                 :                :                      errmsg("cannot convert infinity to %s", "smallint")));
                               4570                 :                :     }
                               4571                 :                : 
                               4572                 :                :     /* Convert to variable format and thence to int8 */
 4162 heikki.linnakangas@i     4573                 :             39 :     init_var_from_num(num, &x);
                               4574                 :                : 
 3313 andres@anarazel.de       4575         [ -  + ]:             39 :     if (!numericvar_to_int64(&x, &val))
 7567 tgl@sss.pgh.pa.us        4576         [ #  # ]:UBC           0 :         ereport(ERROR,
                               4577                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4578                 :                :                  errmsg("smallint out of range")));
                               4579                 :                : 
  982 dean.a.rasheed@gmail     4580   [ +  +  +  + ]:CBC          39 :     if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
 7567 tgl@sss.pgh.pa.us        4581         [ +  - ]:              6 :         ereport(ERROR,
                               4582                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4583                 :                :                  errmsg("smallint out of range")));
                               4584                 :                : 
                               4585                 :                :     /* Down-convert to int2 */
  982 dean.a.rasheed@gmail     4586                 :             33 :     result = (int16) val;
                               4587                 :                : 
 7695 tgl@sss.pgh.pa.us        4588                 :             33 :     PG_RETURN_INT16(result);
                               4589                 :                : }
                               4590                 :                : 
                               4591                 :                : 
                               4592                 :                : Datum
 8660                          4593                 :            537 : float8_numeric(PG_FUNCTION_ARGS)
                               4594                 :                : {
                               4595                 :            537 :     float8      val = PG_GETARG_FLOAT8(0);
                               4596                 :                :     Numeric     res;
                               4597                 :                :     NumericVar  result;
                               4598                 :                :     char        buf[DBL_DIG + 100];
                               4599                 :                :     const char *endptr;
                               4600                 :                : 
                               4601         [ +  + ]:            537 :     if (isnan(val))
                               4602                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               4603                 :                : 
 2391                          4604         [ +  + ]:            534 :     if (isinf(val))
                               4605                 :                :     {
 1362                          4606         [ +  + ]:              6 :         if (val < 0)
                               4607                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
                               4608                 :                :         else
                               4609                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4610                 :                :     }
                               4611                 :                : 
 2391                          4612                 :            528 :     snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
                               4613                 :                : 
 9237 JanWieck@Yahoo.com       4614                 :            528 :     init_var(&result);
                               4615                 :                : 
                               4616                 :                :     /* Assume we need not worry about leading/trailing spaces */
  492 tgl@sss.pgh.pa.us        4617                 :            528 :     (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
                               4618                 :                : 
 9237 JanWieck@Yahoo.com       4619                 :            528 :     res = make_result(&result);
                               4620                 :                : 
                               4621                 :            528 :     free_var(&result);
                               4622                 :                : 
 8660 tgl@sss.pgh.pa.us        4623                 :            528 :     PG_RETURN_NUMERIC(res);
                               4624                 :                : }
                               4625                 :                : 
                               4626                 :                : 
                               4627                 :                : Datum
                               4628                 :         259637 : numeric_float8(PG_FUNCTION_ARGS)
                               4629                 :                : {
                               4630                 :         259637 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4631                 :                :     char       *tmp;
                               4632                 :                :     Datum       result;
                               4633                 :                : 
 1362                          4634         [ +  + ]:         259637 :     if (NUMERIC_IS_SPECIAL(num))
                               4635                 :                :     {
                               4636         [ +  + ]:             39 :         if (NUMERIC_IS_PINF(num))
                               4637                 :             12 :             PG_RETURN_FLOAT8(get_float8_infinity());
                               4638         [ +  + ]:             27 :         else if (NUMERIC_IS_NINF(num))
                               4639                 :             12 :             PG_RETURN_FLOAT8(-get_float8_infinity());
                               4640                 :                :         else
                               4641                 :             15 :             PG_RETURN_FLOAT8(get_float8_nan());
                               4642                 :                :     }
                               4643                 :                : 
 8706                          4644                 :         259598 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
                               4645                 :                :                                               NumericGetDatum(num)));
                               4646                 :                : 
 8657                          4647                 :         259598 :     result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
                               4648                 :                : 
 9237 JanWieck@Yahoo.com       4649                 :         259598 :     pfree(tmp);
                               4650                 :                : 
 8657 tgl@sss.pgh.pa.us        4651                 :         259598 :     PG_RETURN_DATUM(result);
                               4652                 :                : }
                               4653                 :                : 
                               4654                 :                : 
                               4655                 :                : /*
                               4656                 :                :  * Convert numeric to float8; if out of range, return +/- HUGE_VAL
                               4657                 :                :  *
                               4658                 :                :  * (internal helper function, not directly callable from SQL)
                               4659                 :                :  */
                               4660                 :                : Datum
 8219                          4661                 :           1608 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
                               4662                 :                : {
                               4663                 :           1608 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4664                 :                :     double      val;
                               4665                 :                : 
 1362                          4666         [ -  + ]:           1608 :     if (NUMERIC_IS_SPECIAL(num))
                               4667                 :                :     {
 1362 tgl@sss.pgh.pa.us        4668         [ #  # ]:UBC           0 :         if (NUMERIC_IS_PINF(num))
                               4669                 :              0 :             val = HUGE_VAL;
                               4670         [ #  # ]:              0 :         else if (NUMERIC_IS_NINF(num))
                               4671                 :              0 :             val = -HUGE_VAL;
                               4672                 :                :         else
                               4673                 :              0 :             val = get_float8_nan();
                               4674                 :                :     }
                               4675                 :                :     else
                               4676                 :                :     {
                               4677                 :                :         NumericVar  x;
                               4678                 :                : 
 1362 tgl@sss.pgh.pa.us        4679                 :CBC        1608 :         init_var_from_num(num, &x);
                               4680                 :           1608 :         val = numericvar_to_double_no_overflow(&x);
                               4681                 :                :     }
                               4682                 :                : 
 8219                          4683                 :           1608 :     PG_RETURN_FLOAT8(val);
                               4684                 :                : }
                               4685                 :                : 
                               4686                 :                : Datum
 8660                          4687                 :          10887 : float4_numeric(PG_FUNCTION_ARGS)
                               4688                 :                : {
                               4689                 :          10887 :     float4      val = PG_GETARG_FLOAT4(0);
                               4690                 :                :     Numeric     res;
                               4691                 :                :     NumericVar  result;
                               4692                 :                :     char        buf[FLT_DIG + 100];
                               4693                 :                :     const char *endptr;
                               4694                 :                : 
                               4695         [ +  + ]:          10887 :     if (isnan(val))
                               4696                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               4697                 :                : 
 2391                          4698         [ +  + ]:          10884 :     if (isinf(val))
                               4699                 :                :     {
 1362                          4700         [ +  + ]:              6 :         if (val < 0)
                               4701                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
                               4702                 :                :         else
                               4703                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4704                 :                :     }
                               4705                 :                : 
 2391                          4706                 :          10878 :     snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
                               4707                 :                : 
 9237 JanWieck@Yahoo.com       4708                 :          10878 :     init_var(&result);
                               4709                 :                : 
                               4710                 :                :     /* Assume we need not worry about leading/trailing spaces */
  492 tgl@sss.pgh.pa.us        4711                 :          10878 :     (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
                               4712                 :                : 
 9237 JanWieck@Yahoo.com       4713                 :          10878 :     res = make_result(&result);
                               4714                 :                : 
                               4715                 :          10878 :     free_var(&result);
                               4716                 :                : 
 8660 tgl@sss.pgh.pa.us        4717                 :          10878 :     PG_RETURN_NUMERIC(res);
                               4718                 :                : }
                               4719                 :                : 
                               4720                 :                : 
                               4721                 :                : Datum
                               4722                 :           1096 : numeric_float4(PG_FUNCTION_ARGS)
                               4723                 :                : {
                               4724                 :           1096 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4725                 :                :     char       *tmp;
                               4726                 :                :     Datum       result;
                               4727                 :                : 
 1362                          4728         [ +  + ]:           1096 :     if (NUMERIC_IS_SPECIAL(num))
                               4729                 :                :     {
                               4730         [ +  + ]:             39 :         if (NUMERIC_IS_PINF(num))
                               4731                 :             12 :             PG_RETURN_FLOAT4(get_float4_infinity());
                               4732         [ +  + ]:             27 :         else if (NUMERIC_IS_NINF(num))
                               4733                 :             12 :             PG_RETURN_FLOAT4(-get_float4_infinity());
                               4734                 :                :         else
                               4735                 :             15 :             PG_RETURN_FLOAT4(get_float4_nan());
                               4736                 :                :     }
                               4737                 :                : 
 8706                          4738                 :           1057 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
                               4739                 :                :                                               NumericGetDatum(num)));
                               4740                 :                : 
 8657                          4741                 :           1057 :     result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
                               4742                 :                : 
 9237 JanWieck@Yahoo.com       4743                 :           1057 :     pfree(tmp);
                               4744                 :                : 
 8657 tgl@sss.pgh.pa.us        4745                 :           1057 :     PG_RETURN_DATUM(result);
                               4746                 :                : }
                               4747                 :                : 
                               4748                 :                : 
                               4749                 :                : Datum
 1384 fujii@postgresql.org     4750                 :             60 : numeric_pg_lsn(PG_FUNCTION_ARGS)
                               4751                 :                : {
                               4752                 :             60 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4753                 :                :     NumericVar  x;
                               4754                 :                :     XLogRecPtr  result;
                               4755                 :                : 
 1362 tgl@sss.pgh.pa.us        4756         [ +  + ]:             60 :     if (NUMERIC_IS_SPECIAL(num))
                               4757                 :                :     {
                               4758         [ +  - ]:              3 :         if (NUMERIC_IS_NAN(num))
                               4759         [ +  - ]:              3 :             ereport(ERROR,
                               4760                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4761                 :                :                      errmsg("cannot convert NaN to %s", "pg_lsn")));
                               4762                 :                :         else
 1362 tgl@sss.pgh.pa.us        4763         [ #  # ]:UBC           0 :             ereport(ERROR,
                               4764                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4765                 :                :                      errmsg("cannot convert infinity to %s", "pg_lsn")));
                               4766                 :                :     }
                               4767                 :                : 
                               4768                 :                :     /* Convert to variable format and thence to pg_lsn */
 1384 fujii@postgresql.org     4769                 :CBC          57 :     init_var_from_num(num, &x);
                               4770                 :                : 
                               4771         [ +  + ]:             57 :     if (!numericvar_to_uint64(&x, (uint64 *) &result))
                               4772         [ +  - ]:             12 :         ereport(ERROR,
                               4773                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4774                 :                :                  errmsg("pg_lsn out of range")));
                               4775                 :                : 
                               4776                 :             45 :     PG_RETURN_LSN(result);
                               4777                 :                : }
                               4778                 :                : 
                               4779                 :                : 
                               4780                 :                : /* ----------------------------------------------------------------------
                               4781                 :                :  *
                               4782                 :                :  * Aggregate functions
                               4783                 :                :  *
                               4784                 :                :  * The transition datatype for all these aggregates is declared as INTERNAL.
                               4785                 :                :  * Actually, it's a pointer to a NumericAggState allocated in the aggregate
                               4786                 :                :  * context.  The digit buffers for the NumericVars will be there too.
                               4787                 :                :  *
                               4788                 :                :  * On platforms which support 128-bit integers some aggregates instead use a
                               4789                 :                :  * 128-bit integer based transition datatype to speed up calculations.
                               4790                 :                :  *
                               4791                 :                :  * ----------------------------------------------------------------------
                               4792                 :                :  */
                               4793                 :                : 
                               4794                 :                : typedef struct NumericAggState
                               4795                 :                : {
                               4796                 :                :     bool        calcSumX2;      /* if true, calculate sumX2 */
                               4797                 :                :     MemoryContext agg_context;  /* context we're calculating in */
                               4798                 :                :     int64       N;              /* count of processed numbers */
                               4799                 :                :     NumericSumAccum sumX;       /* sum of processed numbers */
                               4800                 :                :     NumericSumAccum sumX2;      /* sum of squares of processed numbers */
                               4801                 :                :     int         maxScale;       /* maximum scale seen so far */
                               4802                 :                :     int64       maxScaleCount;  /* number of values seen with maximum scale */
                               4803                 :                :     /* These counts are *not* included in N!  Use NA_TOTAL_COUNT() as needed */
                               4804                 :                :     int64       NaNcount;       /* count of NaN values */
                               4805                 :                :     int64       pInfcount;      /* count of +Inf values */
                               4806                 :                :     int64       nInfcount;      /* count of -Inf values */
                               4807                 :                : } NumericAggState;
                               4808                 :                : 
                               4809                 :                : #define NA_TOTAL_COUNT(na) \
                               4810                 :                :     ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
                               4811                 :                : 
                               4812                 :                : /*
                               4813                 :                :  * Prepare state data for a numeric aggregate function that needs to compute
                               4814                 :                :  * sum, count and optionally sum of squares of the input.
                               4815                 :                :  */
                               4816                 :                : static NumericAggState *
 3802 tgl@sss.pgh.pa.us        4817                 :          85570 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
                               4818                 :                : {
                               4819                 :                :     NumericAggState *state;
                               4820                 :                :     MemoryContext agg_context;
                               4821                 :                :     MemoryContext old_context;
                               4822                 :                : 
                               4823         [ -  + ]:          85570 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3802 tgl@sss.pgh.pa.us        4824         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               4825                 :                : 
 3802 tgl@sss.pgh.pa.us        4826                 :CBC       85570 :     old_context = MemoryContextSwitchTo(agg_context);
                               4827                 :                : 
                               4828                 :          85570 :     state = (NumericAggState *) palloc0(sizeof(NumericAggState));
                               4829                 :          85570 :     state->calcSumX2 = calcSumX2;
                               4830                 :          85570 :     state->agg_context = agg_context;
                               4831                 :                : 
                               4832                 :          85570 :     MemoryContextSwitchTo(old_context);
                               4833                 :                : 
                               4834                 :          85570 :     return state;
                               4835                 :                : }
                               4836                 :                : 
                               4837                 :                : /*
                               4838                 :                :  * Like makeNumericAggState(), but allocate the state in the current memory
                               4839                 :                :  * context.
                               4840                 :                :  */
                               4841                 :                : static NumericAggState *
 2852                          4842                 :             42 : makeNumericAggStateCurrentContext(bool calcSumX2)
                               4843                 :                : {
                               4844                 :                :     NumericAggState *state;
                               4845                 :                : 
                               4846                 :             42 :     state = (NumericAggState *) palloc0(sizeof(NumericAggState));
                               4847                 :             42 :     state->calcSumX2 = calcSumX2;
                               4848                 :             42 :     state->agg_context = CurrentMemoryContext;
                               4849                 :                : 
                               4850                 :             42 :     return state;
                               4851                 :                : }
                               4852                 :                : 
                               4853                 :                : /*
                               4854                 :                :  * Accumulate a new input value for numeric aggregate functions.
                               4855                 :                :  */
                               4856                 :                : static void
 3802                          4857                 :        1056776 : do_numeric_accum(NumericAggState *state, Numeric newval)
                               4858                 :                : {
                               4859                 :                :     NumericVar  X;
                               4860                 :                :     NumericVar  X2;
                               4861                 :                :     MemoryContext old_context;
                               4862                 :                : 
                               4863                 :                :     /* Count NaN/infinity inputs separately from all else */
 1362                          4864         [ +  + ]:        1056776 :     if (NUMERIC_IS_SPECIAL(newval))
                               4865                 :                :     {
                               4866         [ +  + ]:             81 :         if (NUMERIC_IS_PINF(newval))
                               4867                 :             36 :             state->pInfcount++;
                               4868         [ +  + ]:             45 :         else if (NUMERIC_IS_NINF(newval))
                               4869                 :             18 :             state->nInfcount++;
                               4870                 :                :         else
                               4871                 :             27 :             state->NaNcount++;
 3802                          4872                 :             81 :         return;
                               4873                 :                :     }
                               4874                 :                : 
                               4875                 :                :     /* load processed number in short-lived context */
                               4876                 :        1056695 :     init_var_from_num(newval, &X);
                               4877                 :                : 
                               4878                 :                :     /*
                               4879                 :                :      * Track the highest input dscale that we've seen, to support inverse
                               4880                 :                :      * transitions (see do_numeric_discard).
                               4881                 :                :      */
 3655                          4882         [ +  + ]:        1056695 :     if (X.dscale > state->maxScale)
                               4883                 :                :     {
                               4884                 :             78 :         state->maxScale = X.dscale;
                               4885                 :             78 :         state->maxScaleCount = 1;
                               4886                 :                :     }
                               4887         [ +  + ]:        1056617 :     else if (X.dscale == state->maxScale)
                               4888                 :        1056599 :         state->maxScaleCount++;
                               4889                 :                : 
                               4890                 :                :     /* if we need X^2, calculate that in short-lived context */
 3802                          4891         [ +  + ]:        1056695 :     if (state->calcSumX2)
                               4892                 :                :     {
                               4893                 :         120366 :         init_var(&X2);
                               4894                 :         120366 :         mul_var(&X, &X, &X2, X.dscale * 2);
                               4895                 :                :     }
                               4896                 :                : 
                               4897                 :                :     /* The rest of this needs to work in the aggregate context */
                               4898                 :        1056695 :     old_context = MemoryContextSwitchTo(state->agg_context);
                               4899                 :                : 
 2781 heikki.linnakangas@i     4900                 :        1056695 :     state->N++;
                               4901                 :                : 
                               4902                 :                :     /* Accumulate sums */
                               4903                 :        1056695 :     accum_sum_add(&(state->sumX), &X);
                               4904                 :                : 
                               4905         [ +  + ]:        1056695 :     if (state->calcSumX2)
                               4906                 :         120366 :         accum_sum_add(&(state->sumX2), &X2);
                               4907                 :                : 
 3802 tgl@sss.pgh.pa.us        4908                 :        1056695 :     MemoryContextSwitchTo(old_context);
                               4909                 :                : }
                               4910                 :                : 
                               4911                 :                : /*
                               4912                 :                :  * Attempt to remove an input value from the aggregated state.
                               4913                 :                :  *
                               4914                 :                :  * If the value cannot be removed then the function will return false; the
                               4915                 :                :  * possible reasons for failing are described below.
                               4916                 :                :  *
                               4917                 :                :  * If we aggregate the values 1.01 and 2 then the result will be 3.01.
                               4918                 :                :  * If we are then asked to un-aggregate the 1.01 then we must fail as we
                               4919                 :                :  * won't be able to tell what the new aggregated value's dscale should be.
                               4920                 :                :  * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
                               4921                 :                :  * have been zero if we'd really aggregated only 2.
                               4922                 :                :  *
                               4923                 :                :  * Note: alternatively, we could count the number of inputs with each possible
                               4924                 :                :  * dscale (up to some sane limit).  Not yet clear if it's worth the trouble.
                               4925                 :                :  */
                               4926                 :                : static bool
 3655                          4927                 :            171 : do_numeric_discard(NumericAggState *state, Numeric newval)
                               4928                 :                : {
                               4929                 :                :     NumericVar  X;
                               4930                 :                :     NumericVar  X2;
                               4931                 :                :     MemoryContext old_context;
                               4932                 :                : 
                               4933                 :                :     /* Count NaN/infinity inputs separately from all else */
 1362                          4934         [ +  + ]:            171 :     if (NUMERIC_IS_SPECIAL(newval))
                               4935                 :                :     {
                               4936         [ -  + ]:              3 :         if (NUMERIC_IS_PINF(newval))
 1362 tgl@sss.pgh.pa.us        4937                 :UBC           0 :             state->pInfcount--;
 1362 tgl@sss.pgh.pa.us        4938         [ -  + ]:CBC           3 :         else if (NUMERIC_IS_NINF(newval))
 1362 tgl@sss.pgh.pa.us        4939                 :UBC           0 :             state->nInfcount--;
                               4940                 :                :         else
 1362 tgl@sss.pgh.pa.us        4941                 :CBC           3 :             state->NaNcount--;
 3655                          4942                 :              3 :         return true;
                               4943                 :                :     }
                               4944                 :                : 
                               4945                 :                :     /* load processed number in short-lived context */
                               4946                 :            168 :     init_var_from_num(newval, &X);
                               4947                 :                : 
                               4948                 :                :     /*
                               4949                 :                :      * state->sumX's dscale is the maximum dscale of any of the inputs.
                               4950                 :                :      * Removing the last input with that dscale would require us to recompute
                               4951                 :                :      * the maximum dscale of the *remaining* inputs, which we cannot do unless
                               4952                 :                :      * no more non-NaN inputs remain at all.  So we report a failure instead,
                               4953                 :                :      * and force the aggregation to be redone from scratch.
                               4954                 :                :      */
                               4955         [ +  - ]:            168 :     if (X.dscale == state->maxScale)
                               4956                 :                :     {
                               4957   [ +  +  +  + ]:            168 :         if (state->maxScaleCount > 1 || state->maxScale == 0)
                               4958                 :                :         {
                               4959                 :                :             /*
                               4960                 :                :              * Some remaining inputs have same dscale, or dscale hasn't gotten
                               4961                 :                :              * above zero anyway
                               4962                 :                :              */
                               4963                 :            159 :             state->maxScaleCount--;
                               4964                 :                :         }
                               4965         [ +  + ]:              9 :         else if (state->N == 1)
                               4966                 :                :         {
                               4967                 :                :             /* No remaining non-NaN inputs at all, so reset maxScale */
                               4968                 :              6 :             state->maxScale = 0;
                               4969                 :              6 :             state->maxScaleCount = 0;
                               4970                 :                :         }
                               4971                 :                :         else
                               4972                 :                :         {
                               4973                 :                :             /* Correct new maxScale is uncertain, must fail */
                               4974                 :              3 :             return false;
                               4975                 :                :         }
                               4976                 :                :     }
                               4977                 :                : 
                               4978                 :                :     /* if we need X^2, calculate that in short-lived context */
                               4979         [ +  + ]:            165 :     if (state->calcSumX2)
                               4980                 :                :     {
                               4981                 :            144 :         init_var(&X2);
                               4982                 :            144 :         mul_var(&X, &X, &X2, X.dscale * 2);
                               4983                 :                :     }
                               4984                 :                : 
                               4985                 :                :     /* The rest of this needs to work in the aggregate context */
                               4986                 :            165 :     old_context = MemoryContextSwitchTo(state->agg_context);
                               4987                 :                : 
                               4988         [ +  + ]:            165 :     if (state->N-- > 1)
                               4989                 :                :     {
                               4990                 :                :         /* Negate X, to subtract it from the sum */
 2781 heikki.linnakangas@i     4991         [ +  - ]:            156 :         X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
                               4992                 :            156 :         accum_sum_add(&(state->sumX), &X);
                               4993                 :                : 
 3655 tgl@sss.pgh.pa.us        4994         [ +  + ]:            156 :         if (state->calcSumX2)
                               4995                 :                :         {
                               4996                 :                :             /* Negate X^2. X^2 is always positive */
 2781 heikki.linnakangas@i     4997                 :            144 :             X2.sign = NUMERIC_NEG;
                               4998                 :            144 :             accum_sum_add(&(state->sumX2), &X2);
                               4999                 :                :         }
                               5000                 :                :     }
                               5001                 :                :     else
                               5002                 :                :     {
                               5003                 :                :         /* Zero the sums */
 3655 tgl@sss.pgh.pa.us        5004         [ -  + ]:              9 :         Assert(state->N == 0);
                               5005                 :                : 
 2781 heikki.linnakangas@i     5006                 :              9 :         accum_sum_reset(&state->sumX);
                               5007         [ -  + ]:              9 :         if (state->calcSumX2)
 2781 heikki.linnakangas@i     5008                 :UBC           0 :             accum_sum_reset(&state->sumX2);
                               5009                 :                :     }
                               5010                 :                : 
 3655 tgl@sss.pgh.pa.us        5011                 :CBC         165 :     MemoryContextSwitchTo(old_context);
                               5012                 :                : 
                               5013                 :            165 :     return true;
                               5014                 :                : }
                               5015                 :                : 
                               5016                 :                : /*
                               5017                 :                :  * Generic transition function for numeric aggregates that require sumX2.
                               5018                 :                :  */
                               5019                 :                : Datum
 8672                          5020                 :            321 : numeric_accum(PG_FUNCTION_ARGS)
                               5021                 :                : {
                               5022                 :                :     NumericAggState *state;
                               5023                 :                : 
 3802                          5024         [ +  + ]:            321 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5025                 :                : 
                               5026                 :                :     /* Create the state data on the first call */
 3655                          5027         [ +  + ]:            321 :     if (state == NULL)
                               5028                 :             87 :         state = makeNumericAggState(fcinfo, true);
                               5029                 :                : 
                               5030         [ +  + ]:            321 :     if (!PG_ARGISNULL(1))
 3802                          5031                 :            312 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
                               5032                 :                : 
                               5033                 :            321 :     PG_RETURN_POINTER(state);
                               5034                 :                : }
                               5035                 :                : 
                               5036                 :                : /*
                               5037                 :                :  * Generic combine function for numeric aggregates which require sumX2
                               5038                 :                :  */
                               5039                 :                : Datum
 2931 rhaas@postgresql.org     5040                 :             18 : numeric_combine(PG_FUNCTION_ARGS)
                               5041                 :                : {
                               5042                 :                :     NumericAggState *state1;
                               5043                 :                :     NumericAggState *state2;
                               5044                 :                :     MemoryContext agg_context;
                               5045                 :                :     MemoryContext old_context;
                               5046                 :                : 
                               5047         [ -  + ]:             18 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 2931 rhaas@postgresql.org     5048         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5049                 :                : 
 2931 rhaas@postgresql.org     5050         [ +  + ]:CBC          18 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5051         [ +  - ]:             18 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
                               5052                 :                : 
                               5053         [ -  + ]:             18 :     if (state2 == NULL)
 2931 rhaas@postgresql.org     5054                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5055                 :                : 
                               5056                 :                :     /* manually copy all fields from state2 to state1 */
 2931 rhaas@postgresql.org     5057         [ +  + ]:CBC          18 :     if (state1 == NULL)
                               5058                 :                :     {
                               5059                 :              9 :         old_context = MemoryContextSwitchTo(agg_context);
                               5060                 :                : 
 2852 tgl@sss.pgh.pa.us        5061                 :              9 :         state1 = makeNumericAggStateCurrentContext(true);
 2931 rhaas@postgresql.org     5062                 :              9 :         state1->N = state2->N;
                               5063                 :              9 :         state1->NaNcount = state2->NaNcount;
 1362 tgl@sss.pgh.pa.us        5064                 :              9 :         state1->pInfcount = state2->pInfcount;
                               5065                 :              9 :         state1->nInfcount = state2->nInfcount;
 2931 rhaas@postgresql.org     5066                 :              9 :         state1->maxScale = state2->maxScale;
                               5067                 :              9 :         state1->maxScaleCount = state2->maxScaleCount;
                               5068                 :                : 
 2781 heikki.linnakangas@i     5069                 :              9 :         accum_sum_copy(&state1->sumX, &state2->sumX);
                               5070                 :              9 :         accum_sum_copy(&state1->sumX2, &state2->sumX2);
                               5071                 :                : 
 2931 rhaas@postgresql.org     5072                 :              9 :         MemoryContextSwitchTo(old_context);
                               5073                 :                : 
                               5074                 :              9 :         PG_RETURN_POINTER(state1);
                               5075                 :                :     }
                               5076                 :                : 
 1403 tgl@sss.pgh.pa.us        5077                 :              9 :     state1->N += state2->N;
                               5078                 :              9 :     state1->NaNcount += state2->NaNcount;
 1362                          5079                 :              9 :     state1->pInfcount += state2->pInfcount;
                               5080                 :              9 :     state1->nInfcount += state2->nInfcount;
                               5081                 :                : 
 2931 rhaas@postgresql.org     5082         [ +  - ]:              9 :     if (state2->N > 0)
                               5083                 :                :     {
                               5084                 :                :         /*
                               5085                 :                :          * These are currently only needed for moving aggregates, but let's do
                               5086                 :                :          * the right thing anyway...
                               5087                 :                :          */
                               5088         [ -  + ]:              9 :         if (state2->maxScale > state1->maxScale)
                               5089                 :                :         {
 2931 rhaas@postgresql.org     5090                 :UBC           0 :             state1->maxScale = state2->maxScale;
                               5091                 :              0 :             state1->maxScaleCount = state2->maxScaleCount;
                               5092                 :                :         }
 2931 rhaas@postgresql.org     5093         [ +  - ]:CBC           9 :         else if (state2->maxScale == state1->maxScale)
                               5094                 :              9 :             state1->maxScaleCount += state2->maxScaleCount;
                               5095                 :                : 
                               5096                 :                :         /* The rest of this needs to work in the aggregate context */
                               5097                 :              9 :         old_context = MemoryContextSwitchTo(agg_context);
                               5098                 :                : 
                               5099                 :                :         /* Accumulate sums */
 2781 heikki.linnakangas@i     5100                 :              9 :         accum_sum_combine(&state1->sumX, &state2->sumX);
                               5101                 :              9 :         accum_sum_combine(&state1->sumX2, &state2->sumX2);
                               5102                 :                : 
 2931 rhaas@postgresql.org     5103                 :              9 :         MemoryContextSwitchTo(old_context);
                               5104                 :                :     }
                               5105                 :              9 :     PG_RETURN_POINTER(state1);
                               5106                 :                : }
                               5107                 :                : 
                               5108                 :                : /*
                               5109                 :                :  * Generic transition function for numeric aggregates that don't require sumX2.
                               5110                 :                :  */
                               5111                 :                : Datum
 6266 bruce@momjian.us         5112                 :         936404 : numeric_avg_accum(PG_FUNCTION_ARGS)
                               5113                 :                : {
                               5114                 :                :     NumericAggState *state;
                               5115                 :                : 
 3802 tgl@sss.pgh.pa.us        5116         [ +  + ]:         936404 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5117                 :                : 
                               5118                 :                :     /* Create the state data on the first call */
 3655                          5119         [ +  + ]:         936404 :     if (state == NULL)
                               5120                 :          85453 :         state = makeNumericAggState(fcinfo, false);
                               5121                 :                : 
                               5122         [ +  + ]:         936404 :     if (!PG_ARGISNULL(1))
 3802                          5123                 :         936374 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
                               5124                 :                : 
 3655                          5125                 :         936404 :     PG_RETURN_POINTER(state);
                               5126                 :                : }
                               5127                 :                : 
                               5128                 :                : /*
                               5129                 :                :  * Combine function for numeric aggregates which don't require sumX2
                               5130                 :                :  */
                               5131                 :                : Datum
 2931 rhaas@postgresql.org     5132                 :             12 : numeric_avg_combine(PG_FUNCTION_ARGS)
                               5133                 :                : {
                               5134                 :                :     NumericAggState *state1;
                               5135                 :                :     NumericAggState *state2;
                               5136                 :                :     MemoryContext agg_context;
                               5137                 :                :     MemoryContext old_context;
                               5138                 :                : 
                               5139         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 2931 rhaas@postgresql.org     5140         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5141                 :                : 
 2931 rhaas@postgresql.org     5142         [ +  + ]:CBC          12 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5143         [ +  - ]:             12 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
                               5144                 :                : 
                               5145         [ -  + ]:             12 :     if (state2 == NULL)
 2931 rhaas@postgresql.org     5146                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5147                 :                : 
                               5148                 :                :     /* manually copy all fields from state2 to state1 */
 2931 rhaas@postgresql.org     5149         [ +  + ]:CBC          12 :     if (state1 == NULL)
                               5150                 :                :     {
                               5151                 :              3 :         old_context = MemoryContextSwitchTo(agg_context);
                               5152                 :                : 
 2852 tgl@sss.pgh.pa.us        5153                 :              3 :         state1 = makeNumericAggStateCurrentContext(false);
 2931 rhaas@postgresql.org     5154                 :              3 :         state1->N = state2->N;
                               5155                 :              3 :         state1->NaNcount = state2->NaNcount;
 1362 tgl@sss.pgh.pa.us        5156                 :              3 :         state1->pInfcount = state2->pInfcount;
                               5157                 :              3 :         state1->nInfcount = state2->nInfcount;
 2931 rhaas@postgresql.org     5158                 :              3 :         state1->maxScale = state2->maxScale;
                               5159                 :              3 :         state1->maxScaleCount = state2->maxScaleCount;
                               5160                 :                : 
 2781 heikki.linnakangas@i     5161                 :              3 :         accum_sum_copy(&state1->sumX, &state2->sumX);
                               5162                 :                : 
 2931 rhaas@postgresql.org     5163                 :              3 :         MemoryContextSwitchTo(old_context);
                               5164                 :                : 
                               5165                 :              3 :         PG_RETURN_POINTER(state1);
                               5166                 :                :     }
                               5167                 :                : 
 1403 tgl@sss.pgh.pa.us        5168                 :              9 :     state1->N += state2->N;
                               5169                 :              9 :     state1->NaNcount += state2->NaNcount;
 1362                          5170                 :              9 :     state1->pInfcount += state2->pInfcount;
                               5171                 :              9 :     state1->nInfcount += state2->nInfcount;
                               5172                 :                : 
 2931 rhaas@postgresql.org     5173         [ +  - ]:              9 :     if (state2->N > 0)
                               5174                 :                :     {
                               5175                 :                :         /*
                               5176                 :                :          * These are currently only needed for moving aggregates, but let's do
                               5177                 :                :          * the right thing anyway...
                               5178                 :                :          */
                               5179         [ -  + ]:              9 :         if (state2->maxScale > state1->maxScale)
                               5180                 :                :         {
 2931 rhaas@postgresql.org     5181                 :UBC           0 :             state1->maxScale = state2->maxScale;
                               5182                 :              0 :             state1->maxScaleCount = state2->maxScaleCount;
                               5183                 :                :         }
 2931 rhaas@postgresql.org     5184         [ +  - ]:CBC           9 :         else if (state2->maxScale == state1->maxScale)
                               5185                 :              9 :             state1->maxScaleCount += state2->maxScaleCount;
                               5186                 :                : 
                               5187                 :                :         /* The rest of this needs to work in the aggregate context */
                               5188                 :              9 :         old_context = MemoryContextSwitchTo(agg_context);
                               5189                 :                : 
                               5190                 :                :         /* Accumulate sums */
 2781 heikki.linnakangas@i     5191                 :              9 :         accum_sum_combine(&state1->sumX, &state2->sumX);
                               5192                 :                : 
 2931 rhaas@postgresql.org     5193                 :              9 :         MemoryContextSwitchTo(old_context);
                               5194                 :                :     }
                               5195                 :              9 :     PG_RETURN_POINTER(state1);
                               5196                 :                : }
                               5197                 :                : 
                               5198                 :                : /*
                               5199                 :                :  * numeric_avg_serialize
                               5200                 :                :  *      Serialize NumericAggState for numeric aggregates that don't require
                               5201                 :                :  *      sumX2.
                               5202                 :                :  */
                               5203                 :                : Datum
                               5204                 :             12 : numeric_avg_serialize(PG_FUNCTION_ARGS)
                               5205                 :                : {
                               5206                 :                :     NumericAggState *state;
                               5207                 :                :     StringInfoData buf;
                               5208                 :                :     bytea      *result;
                               5209                 :                :     NumericVar  tmp_var;
                               5210                 :                : 
                               5211                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5212         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5213         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5214                 :                : 
 2931 rhaas@postgresql.org     5215                 :CBC          12 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
                               5216                 :                : 
 2781 heikki.linnakangas@i     5217                 :             12 :     init_var(&tmp_var);
                               5218                 :                : 
 2931 rhaas@postgresql.org     5219                 :             12 :     pq_begintypsend(&buf);
                               5220                 :                : 
                               5221                 :                :     /* N */
                               5222                 :             12 :     pq_sendint64(&buf, state->N);
                               5223                 :                : 
                               5224                 :                :     /* sumX */
 1014 dean.a.rasheed@gmail     5225                 :             12 :     accum_sum_final(&state->sumX, &tmp_var);
                               5226                 :             12 :     numericvar_serialize(&buf, &tmp_var);
                               5227                 :                : 
                               5228                 :                :     /* maxScale */
 2377 andres@anarazel.de       5229                 :             12 :     pq_sendint32(&buf, state->maxScale);
                               5230                 :                : 
                               5231                 :                :     /* maxScaleCount */
 2931 rhaas@postgresql.org     5232                 :             12 :     pq_sendint64(&buf, state->maxScaleCount);
                               5233                 :                : 
                               5234                 :                :     /* NaNcount */
                               5235                 :             12 :     pq_sendint64(&buf, state->NaNcount);
                               5236                 :                : 
                               5237                 :                :     /* pInfcount */
 1362 tgl@sss.pgh.pa.us        5238                 :             12 :     pq_sendint64(&buf, state->pInfcount);
                               5239                 :                : 
                               5240                 :                :     /* nInfcount */
                               5241                 :             12 :     pq_sendint64(&buf, state->nInfcount);
                               5242                 :                : 
 2931 rhaas@postgresql.org     5243                 :             12 :     result = pq_endtypsend(&buf);
                               5244                 :                : 
 1014 dean.a.rasheed@gmail     5245                 :             12 :     free_var(&tmp_var);
                               5246                 :                : 
 2931 rhaas@postgresql.org     5247                 :             12 :     PG_RETURN_BYTEA_P(result);
                               5248                 :                : }
                               5249                 :                : 
                               5250                 :                : /*
                               5251                 :                :  * numeric_avg_deserialize
                               5252                 :                :  *      Deserialize bytea into NumericAggState for numeric aggregates that
                               5253                 :                :  *      don't require sumX2.
                               5254                 :                :  */
                               5255                 :                : Datum
                               5256                 :             12 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
                               5257                 :                : {
                               5258                 :                :     bytea      *sstate;
                               5259                 :                :     NumericAggState *result;
                               5260                 :                :     StringInfoData buf;
                               5261                 :                :     NumericVar  tmp_var;
                               5262                 :                : 
                               5263         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5264         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5265                 :                : 
 2590 noah@leadboat.com        5266                 :CBC          12 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5267                 :                : 
 1014 dean.a.rasheed@gmail     5268                 :             12 :     init_var(&tmp_var);
                               5269                 :                : 
                               5270                 :                :     /*
                               5271                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5272                 :                :      * recv-function infrastructure.
                               5273                 :                :      */
  170 drowley@postgresql.o     5274         [ +  - ]:GNC          12 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5275   [ -  +  -  -  :             12 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 - ]
                               5276                 :                : 
 2852 tgl@sss.pgh.pa.us        5277                 :CBC          12 :     result = makeNumericAggStateCurrentContext(false);
                               5278                 :                : 
                               5279                 :                :     /* N */
 2931 rhaas@postgresql.org     5280                 :             12 :     result->N = pq_getmsgint64(&buf);
                               5281                 :                : 
                               5282                 :                :     /* sumX */
 1014 dean.a.rasheed@gmail     5283                 :             12 :     numericvar_deserialize(&buf, &tmp_var);
 2781 heikki.linnakangas@i     5284                 :             12 :     accum_sum_add(&(result->sumX), &tmp_var);
                               5285                 :                : 
                               5286                 :                :     /* maxScale */
 2931 rhaas@postgresql.org     5287                 :             12 :     result->maxScale = pq_getmsgint(&buf, 4);
                               5288                 :                : 
                               5289                 :                :     /* maxScaleCount */
                               5290                 :             12 :     result->maxScaleCount = pq_getmsgint64(&buf);
                               5291                 :                : 
                               5292                 :                :     /* NaNcount */
                               5293                 :             12 :     result->NaNcount = pq_getmsgint64(&buf);
                               5294                 :                : 
                               5295                 :                :     /* pInfcount */
 1362 tgl@sss.pgh.pa.us        5296                 :             12 :     result->pInfcount = pq_getmsgint64(&buf);
                               5297                 :                : 
                               5298                 :                :     /* nInfcount */
                               5299                 :             12 :     result->nInfcount = pq_getmsgint64(&buf);
                               5300                 :                : 
 2931 rhaas@postgresql.org     5301                 :             12 :     pq_getmsgend(&buf);
                               5302                 :                : 
 1014 dean.a.rasheed@gmail     5303                 :             12 :     free_var(&tmp_var);
                               5304                 :                : 
 2931 rhaas@postgresql.org     5305                 :             12 :     PG_RETURN_POINTER(result);
                               5306                 :                : }
                               5307                 :                : 
                               5308                 :                : /*
                               5309                 :                :  * numeric_serialize
                               5310                 :                :  *      Serialization function for NumericAggState for numeric aggregates that
                               5311                 :                :  *      require sumX2.
                               5312                 :                :  */
                               5313                 :                : Datum
                               5314                 :             18 : numeric_serialize(PG_FUNCTION_ARGS)
                               5315                 :                : {
                               5316                 :                :     NumericAggState *state;
                               5317                 :                :     StringInfoData buf;
                               5318                 :                :     bytea      *result;
                               5319                 :                :     NumericVar  tmp_var;
                               5320                 :                : 
                               5321                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5322         [ -  + ]:             18 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5323         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5324                 :                : 
 2931 rhaas@postgresql.org     5325                 :CBC          18 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
                               5326                 :                : 
 2781 heikki.linnakangas@i     5327                 :             18 :     init_var(&tmp_var);
                               5328                 :                : 
 2931 rhaas@postgresql.org     5329                 :             18 :     pq_begintypsend(&buf);
                               5330                 :                : 
                               5331                 :                :     /* N */
                               5332                 :             18 :     pq_sendint64(&buf, state->N);
                               5333                 :                : 
                               5334                 :                :     /* sumX */
 1014 dean.a.rasheed@gmail     5335                 :             18 :     accum_sum_final(&state->sumX, &tmp_var);
                               5336                 :             18 :     numericvar_serialize(&buf, &tmp_var);
                               5337                 :                : 
                               5338                 :                :     /* sumX2 */
                               5339                 :             18 :     accum_sum_final(&state->sumX2, &tmp_var);
                               5340                 :             18 :     numericvar_serialize(&buf, &tmp_var);
                               5341                 :                : 
                               5342                 :                :     /* maxScale */
 2377 andres@anarazel.de       5343                 :             18 :     pq_sendint32(&buf, state->maxScale);
                               5344                 :                : 
                               5345                 :                :     /* maxScaleCount */
 2931 rhaas@postgresql.org     5346                 :             18 :     pq_sendint64(&buf, state->maxScaleCount);
                               5347                 :                : 
                               5348                 :                :     /* NaNcount */
                               5349                 :             18 :     pq_sendint64(&buf, state->NaNcount);
                               5350                 :                : 
                               5351                 :                :     /* pInfcount */
 1362 tgl@sss.pgh.pa.us        5352                 :             18 :     pq_sendint64(&buf, state->pInfcount);
                               5353                 :                : 
                               5354                 :                :     /* nInfcount */
                               5355                 :             18 :     pq_sendint64(&buf, state->nInfcount);
                               5356                 :                : 
 2931 rhaas@postgresql.org     5357                 :             18 :     result = pq_endtypsend(&buf);
                               5358                 :                : 
 1014 dean.a.rasheed@gmail     5359                 :             18 :     free_var(&tmp_var);
                               5360                 :                : 
 2931 rhaas@postgresql.org     5361                 :             18 :     PG_RETURN_BYTEA_P(result);
                               5362                 :                : }
                               5363                 :                : 
                               5364                 :                : /*
                               5365                 :                :  * numeric_deserialize
                               5366                 :                :  *      Deserialization function for NumericAggState for numeric aggregates that
                               5367                 :                :  *      require sumX2.
                               5368                 :                :  */
                               5369                 :                : Datum
                               5370                 :             18 : numeric_deserialize(PG_FUNCTION_ARGS)
                               5371                 :                : {
                               5372                 :                :     bytea      *sstate;
                               5373                 :                :     NumericAggState *result;
                               5374                 :                :     StringInfoData buf;
                               5375                 :                :     NumericVar  tmp_var;
                               5376                 :                : 
                               5377         [ -  + ]:             18 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5378         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5379                 :                : 
 2590 noah@leadboat.com        5380                 :CBC          18 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5381                 :                : 
 1014 dean.a.rasheed@gmail     5382                 :             18 :     init_var(&tmp_var);
                               5383                 :                : 
                               5384                 :                :     /*
                               5385                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5386                 :                :      * recv-function infrastructure.
                               5387                 :                :      */
  170 drowley@postgresql.o     5388         [ +  + ]:GNC          18 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5389   [ -  +  -  -  :             18 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 + ]
                               5390                 :                : 
 2852 tgl@sss.pgh.pa.us        5391                 :CBC          18 :     result = makeNumericAggStateCurrentContext(false);
                               5392                 :                : 
                               5393                 :                :     /* N */
 2931 rhaas@postgresql.org     5394                 :             18 :     result->N = pq_getmsgint64(&buf);
                               5395                 :                : 
                               5396                 :                :     /* sumX */
 1014 dean.a.rasheed@gmail     5397                 :             18 :     numericvar_deserialize(&buf, &tmp_var);
                               5398                 :             18 :     accum_sum_add(&(result->sumX), &tmp_var);
                               5399                 :                : 
                               5400                 :                :     /* sumX2 */
                               5401                 :             18 :     numericvar_deserialize(&buf, &tmp_var);
                               5402                 :             18 :     accum_sum_add(&(result->sumX2), &tmp_var);
                               5403                 :                : 
                               5404                 :                :     /* maxScale */
 2931 rhaas@postgresql.org     5405                 :             18 :     result->maxScale = pq_getmsgint(&buf, 4);
                               5406                 :                : 
                               5407                 :                :     /* maxScaleCount */
                               5408                 :             18 :     result->maxScaleCount = pq_getmsgint64(&buf);
                               5409                 :                : 
                               5410                 :                :     /* NaNcount */
                               5411                 :             18 :     result->NaNcount = pq_getmsgint64(&buf);
                               5412                 :                : 
                               5413                 :                :     /* pInfcount */
 1362 tgl@sss.pgh.pa.us        5414                 :             18 :     result->pInfcount = pq_getmsgint64(&buf);
                               5415                 :                : 
                               5416                 :                :     /* nInfcount */
                               5417                 :             18 :     result->nInfcount = pq_getmsgint64(&buf);
                               5418                 :                : 
 2931 rhaas@postgresql.org     5419                 :             18 :     pq_getmsgend(&buf);
                               5420                 :                : 
 1014 dean.a.rasheed@gmail     5421                 :             18 :     free_var(&tmp_var);
                               5422                 :                : 
 2931 rhaas@postgresql.org     5423                 :             18 :     PG_RETURN_POINTER(result);
                               5424                 :                : }
                               5425                 :                : 
                               5426                 :                : /*
                               5427                 :                :  * Generic inverse transition function for numeric aggregates
                               5428                 :                :  * (with or without requirement for X^2).
                               5429                 :                :  */
                               5430                 :                : Datum
 3655 tgl@sss.pgh.pa.us        5431                 :            114 : numeric_accum_inv(PG_FUNCTION_ARGS)
                               5432                 :                : {
                               5433                 :                :     NumericAggState *state;
                               5434                 :                : 
                               5435         [ +  - ]:            114 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5436                 :                : 
                               5437                 :                :     /* Should not get here with no state */
                               5438         [ -  + ]:            114 :     if (state == NULL)
 3655 tgl@sss.pgh.pa.us        5439         [ #  # ]:UBC           0 :         elog(ERROR, "numeric_accum_inv called with NULL state");
                               5440                 :                : 
 3655 tgl@sss.pgh.pa.us        5441         [ +  + ]:CBC         114 :     if (!PG_ARGISNULL(1))
                               5442                 :                :     {
                               5443                 :                :         /* If we fail to perform the inverse transition, return NULL */
                               5444         [ +  + ]:             99 :         if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
                               5445                 :              3 :             PG_RETURN_NULL();
                               5446                 :                :     }
                               5447                 :                : 
 3802                          5448                 :            111 :     PG_RETURN_POINTER(state);
                               5449                 :                : }
                               5450                 :                : 
                               5451                 :                : 
                               5452                 :                : /*
                               5453                 :                :  * Integer data types in general use Numeric accumulators to share code
                               5454                 :                :  * and avoid risk of overflow.
                               5455                 :                :  *
                               5456                 :                :  * However for performance reasons optimized special-purpose accumulator
                               5457                 :                :  * routines are used when possible.
                               5458                 :                :  *
                               5459                 :                :  * On platforms with 128-bit integer support, the 128-bit routines will be
                               5460                 :                :  * used when sum(X) or sum(X*X) fit into 128-bit.
                               5461                 :                :  *
                               5462                 :                :  * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
                               5463                 :                :  * accumulators will be used for SUM and AVG of these data types.
                               5464                 :                :  */
                               5465                 :                : 
                               5466                 :                : #ifdef HAVE_INT128
                               5467                 :                : typedef struct Int128AggState
                               5468                 :                : {
                               5469                 :                :     bool        calcSumX2;      /* if true, calculate sumX2 */
                               5470                 :                :     int64       N;              /* count of processed numbers */
                               5471                 :                :     int128      sumX;           /* sum of processed numbers */
                               5472                 :                :     int128      sumX2;          /* sum of squares of processed numbers */
                               5473                 :                : } Int128AggState;
                               5474                 :                : 
                               5475                 :                : /*
                               5476                 :                :  * Prepare state data for a 128-bit aggregate function that needs to compute
                               5477                 :                :  * sum, count and optionally sum of squares of the input.
                               5478                 :                :  */
                               5479                 :                : static Int128AggState *
 3313 andres@anarazel.de       5480                 :            360 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
                               5481                 :                : {
                               5482                 :                :     Int128AggState *state;
                               5483                 :                :     MemoryContext agg_context;
                               5484                 :                :     MemoryContext old_context;
                               5485                 :                : 
                               5486         [ -  + ]:            360 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3313 andres@anarazel.de       5487         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5488                 :                : 
 3313 andres@anarazel.de       5489                 :CBC         360 :     old_context = MemoryContextSwitchTo(agg_context);
                               5490                 :                : 
                               5491                 :            360 :     state = (Int128AggState *) palloc0(sizeof(Int128AggState));
                               5492                 :            360 :     state->calcSumX2 = calcSumX2;
                               5493                 :                : 
                               5494                 :            360 :     MemoryContextSwitchTo(old_context);
                               5495                 :                : 
                               5496                 :            360 :     return state;
                               5497                 :                : }
                               5498                 :                : 
                               5499                 :                : /*
                               5500                 :                :  * Like makeInt128AggState(), but allocate the state in the current memory
                               5501                 :                :  * context.
                               5502                 :                :  */
                               5503                 :                : static Int128AggState *
 2852 tgl@sss.pgh.pa.us        5504                 :             39 : makeInt128AggStateCurrentContext(bool calcSumX2)
                               5505                 :                : {
                               5506                 :                :     Int128AggState *state;
                               5507                 :                : 
                               5508                 :             39 :     state = (Int128AggState *) palloc0(sizeof(Int128AggState));
                               5509                 :             39 :     state->calcSumX2 = calcSumX2;
                               5510                 :                : 
                               5511                 :             39 :     return state;
                               5512                 :                : }
                               5513                 :                : 
                               5514                 :                : /*
                               5515                 :                :  * Accumulate a new input value for 128-bit aggregate functions.
                               5516                 :                :  */
                               5517                 :                : static void
 3313 andres@anarazel.de       5518                 :         276769 : do_int128_accum(Int128AggState *state, int128 newval)
                               5519                 :                : {
                               5520         [ +  + ]:         276769 :     if (state->calcSumX2)
                               5521                 :         121180 :         state->sumX2 += newval * newval;
                               5522                 :                : 
                               5523                 :         276769 :     state->sumX += newval;
                               5524                 :         276769 :     state->N++;
                               5525                 :         276769 : }
                               5526                 :                : 
                               5527                 :                : /*
                               5528                 :                :  * Remove an input value from the aggregated state.
                               5529                 :                :  */
                               5530                 :                : static void
                               5531                 :            156 : do_int128_discard(Int128AggState *state, int128 newval)
                               5532                 :                : {
                               5533         [ +  + ]:            156 :     if (state->calcSumX2)
                               5534                 :            144 :         state->sumX2 -= newval * newval;
                               5535                 :                : 
                               5536                 :            156 :     state->sumX -= newval;
                               5537                 :            156 :     state->N--;
                               5538                 :            156 : }
                               5539                 :                : 
                               5540                 :                : typedef Int128AggState PolyNumAggState;
                               5541                 :                : #define makePolyNumAggState makeInt128AggState
                               5542                 :                : #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
                               5543                 :                : #else
                               5544                 :                : typedef NumericAggState PolyNumAggState;
                               5545                 :                : #define makePolyNumAggState makeNumericAggState
                               5546                 :                : #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
                               5547                 :                : #endif
                               5548                 :                : 
                               5549                 :                : Datum
 8672 tgl@sss.pgh.pa.us        5550                 :             99 : int2_accum(PG_FUNCTION_ARGS)
                               5551                 :                : {
                               5552                 :                :     PolyNumAggState *state;
                               5553                 :                : 
 3313 andres@anarazel.de       5554         [ +  + ]:             99 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5555                 :                : 
                               5556                 :                :     /* Create the state data on the first call */
 3655 tgl@sss.pgh.pa.us        5557         [ +  + ]:             99 :     if (state == NULL)
 3313 andres@anarazel.de       5558                 :             18 :         state = makePolyNumAggState(fcinfo, true);
                               5559                 :                : 
 3802 tgl@sss.pgh.pa.us        5560         [ +  + ]:             99 :     if (!PG_ARGISNULL(1))
                               5561                 :                :     {
                               5562                 :                : #ifdef HAVE_INT128
 3311 andres@anarazel.de       5563                 :             90 :         do_int128_accum(state, (int128) PG_GETARG_INT16(1));
                               5564                 :                : #else
                               5565                 :                :         do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT16(1)));
                               5566                 :                : #endif
                               5567                 :                :     }
                               5568                 :                : 
 3802 tgl@sss.pgh.pa.us        5569                 :             99 :     PG_RETURN_POINTER(state);
                               5570                 :                : }
                               5571                 :                : 
                               5572                 :                : Datum
 8672                          5573                 :         121099 : int4_accum(PG_FUNCTION_ARGS)
                               5574                 :                : {
                               5575                 :                :     PolyNumAggState *state;
                               5576                 :                : 
 3313 andres@anarazel.de       5577         [ +  + ]:         121099 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5578                 :                : 
                               5579                 :                :     /* Create the state data on the first call */
 3655 tgl@sss.pgh.pa.us        5580         [ +  + ]:         121099 :     if (state == NULL)
 3313 andres@anarazel.de       5581                 :             40 :         state = makePolyNumAggState(fcinfo, true);
                               5582                 :                : 
 3802 tgl@sss.pgh.pa.us        5583         [ +  + ]:         121099 :     if (!PG_ARGISNULL(1))
                               5584                 :                :     {
                               5585                 :                : #ifdef HAVE_INT128
 3313 andres@anarazel.de       5586                 :         121090 :         do_int128_accum(state, (int128) PG_GETARG_INT32(1));
                               5587                 :                : #else
                               5588                 :                :         do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT32(1)));
                               5589                 :                : #endif
                               5590                 :                :     }
                               5591                 :                : 
 3802 tgl@sss.pgh.pa.us        5592                 :         121099 :     PG_RETURN_POINTER(state);
                               5593                 :                : }
                               5594                 :                : 
                               5595                 :                : Datum
 8672                          5596                 :         120099 : int8_accum(PG_FUNCTION_ARGS)
                               5597                 :                : {
                               5598                 :                :     NumericAggState *state;
                               5599                 :                : 
 3802                          5600         [ +  + ]:         120099 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5601                 :                : 
                               5602                 :                :     /* Create the state data on the first call */
 3655                          5603         [ +  + ]:         120099 :     if (state == NULL)
                               5604                 :             30 :         state = makeNumericAggState(fcinfo, true);
                               5605                 :                : 
 3802                          5606         [ +  + ]:         120099 :     if (!PG_ARGISNULL(1))
 1313 peter@eisentraut.org     5607                 :         120090 :         do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
                               5608                 :                : 
 3802 tgl@sss.pgh.pa.us        5609                 :         120099 :     PG_RETURN_POINTER(state);
                               5610                 :                : }
                               5611                 :                : 
                               5612                 :                : /*
                               5613                 :                :  * Combine function for numeric aggregates which require sumX2
                               5614                 :                :  */
                               5615                 :                : Datum
 2931 rhaas@postgresql.org     5616                 :             12 : numeric_poly_combine(PG_FUNCTION_ARGS)
                               5617                 :                : {
                               5618                 :                :     PolyNumAggState *state1;
                               5619                 :                :     PolyNumAggState *state2;
                               5620                 :                :     MemoryContext agg_context;
                               5621                 :                :     MemoryContext old_context;
                               5622                 :                : 
                               5623         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 2931 rhaas@postgresql.org     5624         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5625                 :                : 
 2931 rhaas@postgresql.org     5626         [ +  + ]:CBC          12 :     state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5627         [ +  - ]:             12 :     state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
                               5628                 :                : 
                               5629         [ -  + ]:             12 :     if (state2 == NULL)
 2931 rhaas@postgresql.org     5630                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5631                 :                : 
                               5632                 :                :     /* manually copy all fields from state2 to state1 */
 2931 rhaas@postgresql.org     5633         [ +  + ]:CBC          12 :     if (state1 == NULL)
                               5634                 :                :     {
                               5635                 :              3 :         old_context = MemoryContextSwitchTo(agg_context);
                               5636                 :                : 
                               5637                 :              3 :         state1 = makePolyNumAggState(fcinfo, true);
                               5638                 :              3 :         state1->N = state2->N;
                               5639                 :                : 
                               5640                 :                : #ifdef HAVE_INT128
                               5641                 :              3 :         state1->sumX = state2->sumX;
                               5642                 :              3 :         state1->sumX2 = state2->sumX2;
                               5643                 :                : #else
                               5644                 :                :         accum_sum_copy(&state1->sumX, &state2->sumX);
                               5645                 :                :         accum_sum_copy(&state1->sumX2, &state2->sumX2);
                               5646                 :                : #endif
                               5647                 :                : 
                               5648                 :              3 :         MemoryContextSwitchTo(old_context);
                               5649                 :                : 
                               5650                 :              3 :         PG_RETURN_POINTER(state1);
                               5651                 :                :     }
                               5652                 :                : 
                               5653         [ +  - ]:              9 :     if (state2->N > 0)
                               5654                 :                :     {
                               5655                 :              9 :         state1->N += state2->N;
                               5656                 :                : 
                               5657                 :                : #ifdef HAVE_INT128
                               5658                 :              9 :         state1->sumX += state2->sumX;
                               5659                 :              9 :         state1->sumX2 += state2->sumX2;
                               5660                 :                : #else
                               5661                 :                :         /* The rest of this needs to work in the aggregate context */
                               5662                 :                :         old_context = MemoryContextSwitchTo(agg_context);
                               5663                 :                : 
                               5664                 :                :         /* Accumulate sums */
                               5665                 :                :         accum_sum_combine(&state1->sumX, &state2->sumX);
                               5666                 :                :         accum_sum_combine(&state1->sumX2, &state2->sumX2);
                               5667                 :                : 
                               5668                 :                :         MemoryContextSwitchTo(old_context);
                               5669                 :                : #endif
                               5670                 :                : 
                               5671                 :                :     }
                               5672                 :              9 :     PG_RETURN_POINTER(state1);
                               5673                 :                : }
                               5674                 :                : 
                               5675                 :                : /*
                               5676                 :                :  * numeric_poly_serialize
                               5677                 :                :  *      Serialize PolyNumAggState into bytea for aggregate functions which
                               5678                 :                :  *      require sumX2.
                               5679                 :                :  */
                               5680                 :                : Datum
                               5681                 :             12 : numeric_poly_serialize(PG_FUNCTION_ARGS)
                               5682                 :                : {
                               5683                 :                :     PolyNumAggState *state;
                               5684                 :                :     StringInfoData buf;
                               5685                 :                :     bytea      *result;
                               5686                 :                :     NumericVar  tmp_var;
                               5687                 :                : 
                               5688                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5689         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5690         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5691                 :                : 
 2931 rhaas@postgresql.org     5692                 :CBC          12 :     state = (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5693                 :                : 
                               5694                 :                :     /*
                               5695                 :                :      * If the platform supports int128 then sumX and sumX2 will be a 128 bit
                               5696                 :                :      * integer type. Here we'll convert that into a numeric type so that the
                               5697                 :                :      * combine state is in the same format for both int128 enabled machines
                               5698                 :                :      * and machines which don't support that type. The logic here is that one
                               5699                 :                :      * day we might like to send these over to another server for further
                               5700                 :                :      * processing and we want a standard format to work with.
                               5701                 :                :      */
                               5702                 :                : 
 1014 dean.a.rasheed@gmail     5703                 :             12 :     init_var(&tmp_var);
                               5704                 :                : 
 2931 rhaas@postgresql.org     5705                 :             12 :     pq_begintypsend(&buf);
                               5706                 :                : 
                               5707                 :                :     /* N */
                               5708                 :             12 :     pq_sendint64(&buf, state->N);
                               5709                 :                : 
                               5710                 :                :     /* sumX */
                               5711                 :                : #ifdef HAVE_INT128
 1014 dean.a.rasheed@gmail     5712                 :             12 :     int128_to_numericvar(state->sumX, &tmp_var);
                               5713                 :                : #else
                               5714                 :                :     accum_sum_final(&state->sumX, &tmp_var);
                               5715                 :                : #endif
                               5716                 :             12 :     numericvar_serialize(&buf, &tmp_var);
                               5717                 :                : 
                               5718                 :                :     /* sumX2 */
                               5719                 :                : #ifdef HAVE_INT128
                               5720                 :             12 :     int128_to_numericvar(state->sumX2, &tmp_var);
                               5721                 :                : #else
                               5722                 :                :     accum_sum_final(&state->sumX2, &tmp_var);
                               5723                 :                : #endif
                               5724                 :             12 :     numericvar_serialize(&buf, &tmp_var);
                               5725                 :                : 
 2931 rhaas@postgresql.org     5726                 :             12 :     result = pq_endtypsend(&buf);
                               5727                 :                : 
 1014 dean.a.rasheed@gmail     5728                 :             12 :     free_var(&tmp_var);
                               5729                 :                : 
 2931 rhaas@postgresql.org     5730                 :             12 :     PG_RETURN_BYTEA_P(result);
                               5731                 :                : }
                               5732                 :                : 
                               5733                 :                : /*
                               5734                 :                :  * numeric_poly_deserialize
                               5735                 :                :  *      Deserialize PolyNumAggState from bytea for aggregate functions which
                               5736                 :                :  *      require sumX2.
                               5737                 :                :  */
                               5738                 :                : Datum
                               5739                 :             12 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
                               5740                 :                : {
                               5741                 :                :     bytea      *sstate;
                               5742                 :                :     PolyNumAggState *result;
                               5743                 :                :     StringInfoData buf;
                               5744                 :                :     NumericVar  tmp_var;
                               5745                 :                : 
                               5746         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5747         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5748                 :                : 
 2590 noah@leadboat.com        5749                 :CBC          12 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5750                 :                : 
 1014 dean.a.rasheed@gmail     5751                 :             12 :     init_var(&tmp_var);
                               5752                 :                : 
                               5753                 :                :     /*
                               5754                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5755                 :                :      * recv-function infrastructure.
                               5756                 :                :      */
  170 drowley@postgresql.o     5757         [ +  - ]:GNC          12 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5758   [ -  +  -  -  :             12 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 - ]
                               5759                 :                : 
 2852 tgl@sss.pgh.pa.us        5760                 :CBC          12 :     result = makePolyNumAggStateCurrentContext(false);
                               5761                 :                : 
                               5762                 :                :     /* N */
 2931 rhaas@postgresql.org     5763                 :             12 :     result->N = pq_getmsgint64(&buf);
                               5764                 :                : 
                               5765                 :                :     /* sumX */
 1014 dean.a.rasheed@gmail     5766                 :             12 :     numericvar_deserialize(&buf, &tmp_var);
                               5767                 :                : #ifdef HAVE_INT128
                               5768                 :             12 :     numericvar_to_int128(&tmp_var, &result->sumX);
                               5769                 :                : #else
                               5770                 :                :     accum_sum_add(&result->sumX, &tmp_var);
                               5771                 :                : #endif
                               5772                 :                : 
                               5773                 :                :     /* sumX2 */
                               5774                 :             12 :     numericvar_deserialize(&buf, &tmp_var);
                               5775                 :                : #ifdef HAVE_INT128
                               5776                 :             12 :     numericvar_to_int128(&tmp_var, &result->sumX2);
                               5777                 :                : #else
                               5778                 :                :     accum_sum_add(&result->sumX2, &tmp_var);
                               5779                 :                : #endif
                               5780                 :                : 
 2931 rhaas@postgresql.org     5781                 :             12 :     pq_getmsgend(&buf);
                               5782                 :                : 
 1014 dean.a.rasheed@gmail     5783                 :             12 :     free_var(&tmp_var);
                               5784                 :                : 
 2931 rhaas@postgresql.org     5785                 :             12 :     PG_RETURN_POINTER(result);
                               5786                 :                : }
                               5787                 :                : 
                               5788                 :                : /*
                               5789                 :                :  * Transition function for int8 input when we don't need sumX2.
                               5790                 :                :  */
                               5791                 :                : Datum
 6266 bruce@momjian.us         5792                 :         156147 : int8_avg_accum(PG_FUNCTION_ARGS)
                               5793                 :                : {
                               5794                 :                :     PolyNumAggState *state;
                               5795                 :                : 
 3313 andres@anarazel.de       5796         [ +  + ]:         156147 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5797                 :                : 
                               5798                 :                :     /* Create the state data on the first call */
 3655 tgl@sss.pgh.pa.us        5799         [ +  + ]:         156147 :     if (state == NULL)
 3313 andres@anarazel.de       5800                 :            293 :         state = makePolyNumAggState(fcinfo, false);
                               5801                 :                : 
 3802 tgl@sss.pgh.pa.us        5802         [ +  + ]:         156147 :     if (!PG_ARGISNULL(1))
                               5803                 :                :     {
                               5804                 :                : #ifdef HAVE_INT128
 3313 andres@anarazel.de       5805                 :         155589 :         do_int128_accum(state, (int128) PG_GETARG_INT64(1));
                               5806                 :                : #else
                               5807                 :                :         do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
                               5808                 :                : #endif
                               5809                 :                :     }
                               5810                 :                : 
 3655 tgl@sss.pgh.pa.us        5811                 :         156147 :     PG_RETURN_POINTER(state);
                               5812                 :                : }
                               5813                 :                : 
                               5814                 :                : /*
                               5815                 :                :  * Combine function for PolyNumAggState for aggregates which don't require
                               5816                 :                :  * sumX2
                               5817                 :                :  */
                               5818                 :                : Datum
 2931 rhaas@postgresql.org     5819                 :             27 : int8_avg_combine(PG_FUNCTION_ARGS)
                               5820                 :                : {
                               5821                 :                :     PolyNumAggState *state1;
                               5822                 :                :     PolyNumAggState *state2;
                               5823                 :                :     MemoryContext agg_context;
                               5824                 :                :     MemoryContext old_context;
                               5825                 :                : 
                               5826         [ -  + ]:             27 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 2931 rhaas@postgresql.org     5827         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5828                 :                : 
 2931 rhaas@postgresql.org     5829         [ +  + ]:CBC          27 :     state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5830         [ +  - ]:             27 :     state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
                               5831                 :                : 
                               5832         [ -  + ]:             27 :     if (state2 == NULL)
 2931 rhaas@postgresql.org     5833                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5834                 :                : 
                               5835                 :                :     /* manually copy all fields from state2 to state1 */
 2931 rhaas@postgresql.org     5836         [ +  + ]:CBC          27 :     if (state1 == NULL)
                               5837                 :                :     {
                               5838                 :              6 :         old_context = MemoryContextSwitchTo(agg_context);
                               5839                 :                : 
                               5840                 :              6 :         state1 = makePolyNumAggState(fcinfo, false);
                               5841                 :              6 :         state1->N = state2->N;
                               5842                 :                : 
                               5843                 :                : #ifdef HAVE_INT128
                               5844                 :              6 :         state1->sumX = state2->sumX;
                               5845                 :                : #else
                               5846                 :                :         accum_sum_copy(&state1->sumX, &state2->sumX);
                               5847                 :                : #endif
                               5848                 :              6 :         MemoryContextSwitchTo(old_context);
                               5849                 :                : 
                               5850                 :              6 :         PG_RETURN_POINTER(state1);
                               5851                 :                :     }
                               5852                 :                : 
                               5853         [ +  - ]:             21 :     if (state2->N > 0)
                               5854                 :                :     {
                               5855                 :             21 :         state1->N += state2->N;
                               5856                 :                : 
                               5857                 :                : #ifdef HAVE_INT128
                               5858                 :             21 :         state1->sumX += state2->sumX;
                               5859                 :                : #else
                               5860                 :                :         /* The rest of this needs to work in the aggregate context */
                               5861                 :                :         old_context = MemoryContextSwitchTo(agg_context);
                               5862                 :                : 
                               5863                 :                :         /* Accumulate sums */
                               5864                 :                :         accum_sum_combine(&state1->sumX, &state2->sumX);
                               5865                 :                : 
                               5866                 :                :         MemoryContextSwitchTo(old_context);
                               5867                 :                : #endif
                               5868                 :                : 
                               5869                 :                :     }
                               5870                 :             21 :     PG_RETURN_POINTER(state1);
                               5871                 :                : }
                               5872                 :                : 
                               5873                 :                : /*
                               5874                 :                :  * int8_avg_serialize
                               5875                 :                :  *      Serialize PolyNumAggState into bytea using the standard
                               5876                 :                :  *      recv-function infrastructure.
                               5877                 :                :  */
                               5878                 :                : Datum
                               5879                 :             27 : int8_avg_serialize(PG_FUNCTION_ARGS)
                               5880                 :                : {
                               5881                 :                :     PolyNumAggState *state;
                               5882                 :                :     StringInfoData buf;
                               5883                 :                :     bytea      *result;
                               5884                 :                :     NumericVar  tmp_var;
                               5885                 :                : 
                               5886                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5887         [ -  + ]:             27 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5888         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5889                 :                : 
 2931 rhaas@postgresql.org     5890                 :CBC          27 :     state = (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5891                 :                : 
                               5892                 :                :     /*
                               5893                 :                :      * If the platform supports int128 then sumX will be a 128 integer type.
                               5894                 :                :      * Here we'll convert that into a numeric type so that the combine state
                               5895                 :                :      * is in the same format for both int128 enabled machines and machines
                               5896                 :                :      * which don't support that type. The logic here is that one day we might
                               5897                 :                :      * like to send these over to another server for further processing and we
                               5898                 :                :      * want a standard format to work with.
                               5899                 :                :      */
                               5900                 :                : 
 1014 dean.a.rasheed@gmail     5901                 :             27 :     init_var(&tmp_var);
                               5902                 :                : 
 2931 rhaas@postgresql.org     5903                 :             27 :     pq_begintypsend(&buf);
                               5904                 :                : 
                               5905                 :                :     /* N */
                               5906                 :             27 :     pq_sendint64(&buf, state->N);
                               5907                 :                : 
                               5908                 :                :     /* sumX */
                               5909                 :                : #ifdef HAVE_INT128
 1014 dean.a.rasheed@gmail     5910                 :             27 :     int128_to_numericvar(state->sumX, &tmp_var);
                               5911                 :                : #else
                               5912                 :                :     accum_sum_final(&state->sumX, &tmp_var);
                               5913                 :                : #endif
                               5914                 :             27 :     numericvar_serialize(&buf, &tmp_var);
                               5915                 :                : 
 2931 rhaas@postgresql.org     5916                 :             27 :     result = pq_endtypsend(&buf);
                               5917                 :                : 
 1014 dean.a.rasheed@gmail     5918                 :             27 :     free_var(&tmp_var);
                               5919                 :                : 
 2931 rhaas@postgresql.org     5920                 :             27 :     PG_RETURN_BYTEA_P(result);
                               5921                 :                : }
                               5922                 :                : 
                               5923                 :                : /*
                               5924                 :                :  * int8_avg_deserialize
                               5925                 :                :  *      Deserialize bytea back into PolyNumAggState.
                               5926                 :                :  */
                               5927                 :                : Datum
                               5928                 :             27 : int8_avg_deserialize(PG_FUNCTION_ARGS)
                               5929                 :                : {
                               5930                 :                :     bytea      *sstate;
                               5931                 :                :     PolyNumAggState *result;
                               5932                 :                :     StringInfoData buf;
                               5933                 :                :     NumericVar  tmp_var;
                               5934                 :                : 
                               5935         [ -  + ]:             27 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     5936         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5937                 :                : 
 2590 noah@leadboat.com        5938                 :CBC          27 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5939                 :                : 
 1014 dean.a.rasheed@gmail     5940                 :             27 :     init_var(&tmp_var);
                               5941                 :                : 
                               5942                 :                :     /*
                               5943                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5944                 :                :      * recv-function infrastructure.
                               5945                 :                :      */
  170 drowley@postgresql.o     5946         [ +  - ]:GNC          27 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5947   [ -  +  -  -  :             27 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 - ]
                               5948                 :                : 
 2852 tgl@sss.pgh.pa.us        5949                 :CBC          27 :     result = makePolyNumAggStateCurrentContext(false);
                               5950                 :                : 
                               5951                 :                :     /* N */
 2931 rhaas@postgresql.org     5952                 :             27 :     result->N = pq_getmsgint64(&buf);
                               5953                 :                : 
                               5954                 :                :     /* sumX */
 1014 dean.a.rasheed@gmail     5955                 :             27 :     numericvar_deserialize(&buf, &tmp_var);
                               5956                 :                : #ifdef HAVE_INT128
                               5957                 :             27 :     numericvar_to_int128(&tmp_var, &result->sumX);
                               5958                 :                : #else
                               5959                 :                :     accum_sum_add(&result->sumX, &tmp_var);
                               5960                 :                : #endif
                               5961                 :                : 
 2931 rhaas@postgresql.org     5962                 :             27 :     pq_getmsgend(&buf);
                               5963                 :                : 
 1014 dean.a.rasheed@gmail     5964                 :             27 :     free_var(&tmp_var);
                               5965                 :                : 
 2931 rhaas@postgresql.org     5966                 :             27 :     PG_RETURN_POINTER(result);
                               5967                 :                : }
                               5968                 :                : 
                               5969                 :                : /*
                               5970                 :                :  * Inverse transition functions to go with the above.
                               5971                 :                :  */
                               5972                 :                : 
                               5973                 :                : Datum
 3655 tgl@sss.pgh.pa.us        5974                 :             81 : int2_accum_inv(PG_FUNCTION_ARGS)
                               5975                 :                : {
                               5976                 :                :     PolyNumAggState *state;
                               5977                 :                : 
 3313 andres@anarazel.de       5978         [ +  - ]:             81 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               5979                 :                : 
                               5980                 :                :     /* Should not get here with no state */
 3655 tgl@sss.pgh.pa.us        5981         [ -  + ]:             81 :     if (state == NULL)
 3655 tgl@sss.pgh.pa.us        5982         [ #  # ]:UBC           0 :         elog(ERROR, "int2_accum_inv called with NULL state");
                               5983                 :                : 
 3655 tgl@sss.pgh.pa.us        5984         [ +  + ]:CBC          81 :     if (!PG_ARGISNULL(1))
                               5985                 :                :     {
                               5986                 :                : #ifdef HAVE_INT128
 3313 andres@anarazel.de       5987                 :             72 :         do_int128_discard(state, (int128) PG_GETARG_INT16(1));
                               5988                 :                : #else
                               5989                 :                :         /* Should never fail, all inputs have dscale 0 */
                               5990                 :                :         if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT16(1))))
                               5991                 :                :             elog(ERROR, "do_numeric_discard failed unexpectedly");
                               5992                 :                : #endif
                               5993                 :                :     }
                               5994                 :                : 
 3802 tgl@sss.pgh.pa.us        5995                 :             81 :     PG_RETURN_POINTER(state);
                               5996                 :                : }
                               5997                 :                : 
                               5998                 :                : Datum
 3655                          5999                 :             81 : int4_accum_inv(PG_FUNCTION_ARGS)
                               6000                 :                : {
                               6001                 :                :     PolyNumAggState *state;
                               6002                 :                : 
 3313 andres@anarazel.de       6003         [ +  - ]:             81 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6004                 :                : 
                               6005                 :                :     /* Should not get here with no state */
 3655 tgl@sss.pgh.pa.us        6006         [ -  + ]:             81 :     if (state == NULL)
 3655 tgl@sss.pgh.pa.us        6007         [ #  # ]:UBC           0 :         elog(ERROR, "int4_accum_inv called with NULL state");
                               6008                 :                : 
 3655 tgl@sss.pgh.pa.us        6009         [ +  + ]:CBC          81 :     if (!PG_ARGISNULL(1))
                               6010                 :                :     {
                               6011                 :                : #ifdef HAVE_INT128
 3313 andres@anarazel.de       6012                 :             72 :         do_int128_discard(state, (int128) PG_GETARG_INT32(1));
                               6013                 :                : #else
                               6014                 :                :         /* Should never fail, all inputs have dscale 0 */
                               6015                 :                :         if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT32(1))))
                               6016                 :                :             elog(ERROR, "do_numeric_discard failed unexpectedly");
                               6017                 :                : #endif
                               6018                 :                :     }
                               6019                 :                : 
 3655 tgl@sss.pgh.pa.us        6020                 :             81 :     PG_RETURN_POINTER(state);
                               6021                 :                : }
                               6022                 :                : 
                               6023                 :                : Datum
                               6024                 :             81 : int8_accum_inv(PG_FUNCTION_ARGS)
                               6025                 :                : {
                               6026                 :                :     NumericAggState *state;
                               6027                 :                : 
                               6028         [ +  - ]:             81 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6029                 :                : 
                               6030                 :                :     /* Should not get here with no state */
                               6031         [ -  + ]:             81 :     if (state == NULL)
 3655 tgl@sss.pgh.pa.us        6032         [ #  # ]:UBC           0 :         elog(ERROR, "int8_accum_inv called with NULL state");
                               6033                 :                : 
 3655 tgl@sss.pgh.pa.us        6034         [ +  + ]:CBC          81 :     if (!PG_ARGISNULL(1))
                               6035                 :                :     {
                               6036                 :                :         /* Should never fail, all inputs have dscale 0 */
 1313 peter@eisentraut.org     6037         [ -  + ]:             72 :         if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
 3655 tgl@sss.pgh.pa.us        6038         [ #  # ]:UBC           0 :             elog(ERROR, "do_numeric_discard failed unexpectedly");
                               6039                 :                :     }
                               6040                 :                : 
 3655 tgl@sss.pgh.pa.us        6041                 :CBC          81 :     PG_RETURN_POINTER(state);
                               6042                 :                : }
                               6043                 :                : 
                               6044                 :                : Datum
 3313 andres@anarazel.de       6045                 :             18 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
                               6046                 :                : {
                               6047                 :                :     PolyNumAggState *state;
                               6048                 :                : 
                               6049         [ +  - ]:             18 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6050                 :                : 
                               6051                 :                :     /* Should not get here with no state */
                               6052         [ -  + ]:             18 :     if (state == NULL)
 3313 andres@anarazel.de       6053         [ #  # ]:UBC           0 :         elog(ERROR, "int8_avg_accum_inv called with NULL state");
                               6054                 :                : 
 3313 andres@anarazel.de       6055         [ +  + ]:CBC          18 :     if (!PG_ARGISNULL(1))
                               6056                 :                :     {
                               6057                 :                : #ifdef HAVE_INT128
                               6058                 :             12 :         do_int128_discard(state, (int128) PG_GETARG_INT64(1));
                               6059                 :                : #else
                               6060                 :                :         /* Should never fail, all inputs have dscale 0 */
                               6061                 :                :         if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
                               6062                 :                :             elog(ERROR, "do_numeric_discard failed unexpectedly");
                               6063                 :                : #endif
                               6064                 :                :     }
                               6065                 :                : 
                               6066                 :             18 :     PG_RETURN_POINTER(state);
                               6067                 :                : }
                               6068                 :                : 
                               6069                 :                : Datum
                               6070                 :            389 : numeric_poly_sum(PG_FUNCTION_ARGS)
                               6071                 :                : {
                               6072                 :                : #ifdef HAVE_INT128
                               6073                 :                :     PolyNumAggState *state;
                               6074                 :                :     Numeric     res;
                               6075                 :                :     NumericVar  result;
                               6076                 :                : 
                               6077         [ +  + ]:            389 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6078                 :                : 
                               6079                 :                :     /* If there were no non-null inputs, return NULL */
                               6080   [ +  +  +  + ]:            389 :     if (state == NULL || state->N == 0)
                               6081                 :             12 :         PG_RETURN_NULL();
                               6082                 :                : 
                               6083                 :            377 :     init_var(&result);
                               6084                 :                : 
                               6085                 :            377 :     int128_to_numericvar(state->sumX, &result);
                               6086                 :                : 
                               6087                 :            377 :     res = make_result(&result);
                               6088                 :                : 
                               6089                 :            377 :     free_var(&result);
                               6090                 :                : 
                               6091                 :            377 :     PG_RETURN_NUMERIC(res);
                               6092                 :                : #else
                               6093                 :                :     return numeric_sum(fcinfo);
                               6094                 :                : #endif
                               6095                 :                : }
                               6096                 :                : 
                               6097                 :                : Datum
                               6098                 :             18 : numeric_poly_avg(PG_FUNCTION_ARGS)
                               6099                 :                : {
                               6100                 :                : #ifdef HAVE_INT128
                               6101                 :                :     PolyNumAggState *state;
                               6102                 :                :     NumericVar  result;
                               6103                 :                :     Datum       countd,
                               6104                 :                :                 sumd;
                               6105                 :                : 
                               6106         [ +  - ]:             18 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6107                 :                : 
                               6108                 :                :     /* If there were no non-null inputs, return NULL */
                               6109   [ +  -  +  + ]:             18 :     if (state == NULL || state->N == 0)
                               6110                 :              9 :         PG_RETURN_NULL();
                               6111                 :                : 
                               6112                 :              9 :     init_var(&result);
                               6113                 :                : 
                               6114                 :              9 :     int128_to_numericvar(state->sumX, &result);
                               6115                 :                : 
 1313 peter@eisentraut.org     6116                 :              9 :     countd = NumericGetDatum(int64_to_numeric(state->N));
 3313 andres@anarazel.de       6117                 :              9 :     sumd = NumericGetDatum(make_result(&result));
                               6118                 :                : 
                               6119                 :              9 :     free_var(&result);
                               6120                 :                : 
                               6121                 :              9 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
                               6122                 :                : #else
                               6123                 :                :     return numeric_avg(fcinfo);
                               6124                 :                : #endif
                               6125                 :                : }
                               6126                 :                : 
                               6127                 :                : Datum
 8672 tgl@sss.pgh.pa.us        6128                 :             39 : numeric_avg(PG_FUNCTION_ARGS)
                               6129                 :                : {
                               6130                 :                :     NumericAggState *state;
                               6131                 :                :     Datum       N_datum;
                               6132                 :                :     Datum       sumX_datum;
                               6133                 :                :     NumericVar  sumX_var;
                               6134                 :                : 
 3802                          6135         [ +  - ]:             39 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6136                 :                : 
                               6137                 :                :     /* If there were no non-null inputs, return NULL */
 1362                          6138   [ +  -  +  + ]:             39 :     if (state == NULL || NA_TOTAL_COUNT(state) == 0)
 3802                          6139                 :              9 :         PG_RETURN_NULL();
                               6140                 :                : 
 3631 bruce@momjian.us         6141         [ +  + ]:             30 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
 3802 tgl@sss.pgh.pa.us        6142                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               6143                 :                : 
                               6144                 :                :     /* adding plus and minus infinities gives NaN */
 1362                          6145   [ +  +  +  + ]:             27 :     if (state->pInfcount > 0 && state->nInfcount > 0)
                               6146                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               6147         [ +  + ]:             24 :     if (state->pInfcount > 0)
                               6148                 :              9 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
                               6149         [ +  + ]:             15 :     if (state->nInfcount > 0)
                               6150                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_ninf));
                               6151                 :                : 
 1313 peter@eisentraut.org     6152                 :             12 :     N_datum = NumericGetDatum(int64_to_numeric(state->N));
                               6153                 :                : 
 2781 heikki.linnakangas@i     6154                 :             12 :     init_var(&sumX_var);
                               6155                 :             12 :     accum_sum_final(&state->sumX, &sumX_var);
                               6156                 :             12 :     sumX_datum = NumericGetDatum(make_result(&sumX_var));
                               6157                 :             12 :     free_var(&sumX_var);
                               6158                 :                : 
 3802 tgl@sss.pgh.pa.us        6159                 :             12 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
                               6160                 :                : }
                               6161                 :                : 
                               6162                 :                : Datum
                               6163                 :          85453 : numeric_sum(PG_FUNCTION_ARGS)
                               6164                 :                : {
                               6165                 :                :     NumericAggState *state;
                               6166                 :                :     NumericVar  sumX_var;
                               6167                 :                :     Numeric     result;
                               6168                 :                : 
                               6169         [ +  - ]:          85453 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6170                 :                : 
                               6171                 :                :     /* If there were no non-null inputs, return NULL */
 1362                          6172   [ +  -  +  + ]:          85453 :     if (state == NULL || NA_TOTAL_COUNT(state) == 0)
 8672                          6173                 :              9 :         PG_RETURN_NULL();
                               6174                 :                : 
 3631 bruce@momjian.us         6175         [ +  + ]:          85444 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
 3802 tgl@sss.pgh.pa.us        6176                 :              9 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               6177                 :                : 
                               6178                 :                :     /* adding plus and minus infinities gives NaN */
 1362                          6179   [ +  +  +  + ]:          85435 :     if (state->pInfcount > 0 && state->nInfcount > 0)
                               6180                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               6181         [ +  + ]:          85432 :     if (state->pInfcount > 0)
                               6182                 :              9 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
                               6183         [ +  + ]:          85423 :     if (state->nInfcount > 0)
                               6184                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_ninf));
                               6185                 :                : 
 2781 heikki.linnakangas@i     6186                 :          85420 :     init_var(&sumX_var);
                               6187                 :          85420 :     accum_sum_final(&state->sumX, &sumX_var);
                               6188                 :          85420 :     result = make_result(&sumX_var);
                               6189                 :          85420 :     free_var(&sumX_var);
                               6190                 :                : 
                               6191                 :          85420 :     PG_RETURN_NUMERIC(result);
                               6192                 :                : }
                               6193                 :                : 
                               6194                 :                : /*
                               6195                 :                :  * Workhorse routine for the standard deviance and variance
                               6196                 :                :  * aggregates. 'state' is aggregate's transition state.
                               6197                 :                :  * 'variance' specifies whether we should calculate the
                               6198                 :                :  * variance or the standard deviation. 'sample' indicates whether the
                               6199                 :                :  * caller is interested in the sample or the population
                               6200                 :                :  * variance/stddev.
                               6201                 :                :  *
                               6202                 :                :  * If appropriate variance statistic is undefined for the input,
                               6203                 :                :  * *is_null is set to true and NULL is returned.
                               6204                 :                :  */
                               6205                 :                : static Numeric
 3802 tgl@sss.pgh.pa.us        6206                 :            493 : numeric_stddev_internal(NumericAggState *state,
                               6207                 :                :                         bool variance, bool sample,
                               6208                 :                :                         bool *is_null)
                               6209                 :                : {
                               6210                 :                :     Numeric     res;
                               6211                 :                :     NumericVar  vN,
                               6212                 :                :                 vsumX,
                               6213                 :                :                 vsumX2,
                               6214                 :                :                 vNminus1;
                               6215                 :                :     int64       totCount;
                               6216                 :                :     int         rscale;
                               6217                 :                : 
                               6218                 :                :     /*
                               6219                 :                :      * Sample stddev and variance are undefined when N <= 1; population stddev
                               6220                 :                :      * is undefined when N == 0.  Return NULL in either case (note that NaNs
                               6221                 :                :      * and infinities count as normal inputs for this purpose).
                               6222                 :                :      */
 1362                          6223   [ +  -  -  + ]:            493 :     if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
                               6224                 :                :     {
 1401 tgl@sss.pgh.pa.us        6225                 :UBC           0 :         *is_null = true;
                               6226                 :              0 :         return NULL;
                               6227                 :                :     }
                               6228                 :                : 
 1401 tgl@sss.pgh.pa.us        6229   [ +  +  +  + ]:CBC         493 :     if (sample && totCount <= 1)
                               6230                 :                :     {
 3802                          6231                 :             66 :         *is_null = true;
                               6232                 :             66 :         return NULL;
                               6233                 :                :     }
                               6234                 :                : 
 6610 neilc@samurai.com        6235                 :            427 :     *is_null = false;
                               6236                 :                : 
                               6237                 :                :     /*
                               6238                 :                :      * Deal with NaN and infinity cases.  By analogy to the behavior of the
                               6239                 :                :      * float8 functions, any infinity input produces NaN output.
                               6240                 :                :      */
 1362 tgl@sss.pgh.pa.us        6241   [ +  +  +  +  :            427 :     if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
                                              +  + ]
 6610 neilc@samurai.com        6242                 :             27 :         return make_result(&const_nan);
                               6243                 :                : 
                               6244                 :                :     /* OK, normal calculation applies */
 3802 tgl@sss.pgh.pa.us        6245                 :            400 :     init_var(&vN);
                               6246                 :            400 :     init_var(&vsumX);
                               6247                 :            400 :     init_var(&vsumX2);
                               6248                 :                : 
 3313 andres@anarazel.de       6249                 :            400 :     int64_to_numericvar(state->N, &vN);
 2781 heikki.linnakangas@i     6250                 :            400 :     accum_sum_final(&(state->sumX), &vsumX);
                               6251                 :            400 :     accum_sum_final(&(state->sumX2), &vsumX2);
                               6252                 :                : 
 7664 tgl@sss.pgh.pa.us        6253                 :            400 :     init_var(&vNminus1);
                               6254                 :            400 :     sub_var(&vN, &const_one, &vNminus1);
                               6255                 :                : 
                               6256                 :                :     /* compute rscale for mul_var calls */
 7695                          6257                 :            400 :     rscale = vsumX.dscale * 2;
                               6258                 :                : 
                               6259                 :            400 :     mul_var(&vsumX, &vsumX, &vsumX, rscale);    /* vsumX = sumX * sumX */
 2489                          6260                 :            400 :     mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
 6402 bruce@momjian.us         6261                 :            400 :     sub_var(&vsumX2, &vsumX, &vsumX2);  /* N * sumX2 - sumX * sumX */
                               6262                 :                : 
 8160 tgl@sss.pgh.pa.us        6263         [ +  + ]:            400 :     if (cmp_var(&vsumX2, &const_zero) <= 0)
                               6264                 :                :     {
                               6265                 :                :         /* Watch out for roundoff error producing a negative numerator */
                               6266                 :             40 :         res = make_result(&const_zero);
                               6267                 :                :     }
                               6268                 :                :     else
                               6269                 :                :     {
 6124                          6270         [ +  + ]:            360 :         if (sample)
 2489                          6271                 :            246 :             mul_var(&vN, &vNminus1, &vNminus1, 0);  /* N * (N - 1) */
                               6272                 :                :         else
 5995 bruce@momjian.us         6273                 :            114 :             mul_var(&vN, &vN, &vNminus1, 0);    /* N * N */
 7695 tgl@sss.pgh.pa.us        6274                 :            360 :         rscale = select_div_scale(&vsumX2, &vNminus1);
 2489                          6275                 :            360 :         div_var(&vsumX2, &vNminus1, &vsumX, rscale, true);  /* variance */
 6610 neilc@samurai.com        6276         [ +  + ]:            360 :         if (!variance)
 6402 bruce@momjian.us         6277                 :            189 :             sqrt_var(&vsumX, &vsumX, rscale);   /* stddev */
                               6278                 :                : 
 8160 tgl@sss.pgh.pa.us        6279                 :            360 :         res = make_result(&vsumX);
                               6280                 :                :     }
                               6281                 :                : 
 8672                          6282                 :            400 :     free_var(&vNminus1);
                               6283                 :            400 :     free_var(&vsumX);
                               6284                 :            400 :     free_var(&vsumX2);
                               6285                 :                : 
 6610 neilc@samurai.com        6286                 :            400 :     return res;
                               6287                 :                : }
                               6288                 :                : 
                               6289                 :                : Datum
                               6290                 :             90 : numeric_var_samp(PG_FUNCTION_ARGS)
                               6291                 :                : {
                               6292                 :                :     NumericAggState *state;
                               6293                 :                :     Numeric     res;
                               6294                 :                :     bool        is_null;
                               6295                 :                : 
 3802 tgl@sss.pgh.pa.us        6296         [ +  - ]:             90 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6297                 :                : 
                               6298                 :             90 :     res = numeric_stddev_internal(state, true, true, &is_null);
                               6299                 :                : 
 6610 neilc@samurai.com        6300         [ +  + ]:             90 :     if (is_null)
 7664 tgl@sss.pgh.pa.us        6301                 :             21 :         PG_RETURN_NULL();
                               6302                 :                :     else
 6610 neilc@samurai.com        6303                 :             69 :         PG_RETURN_NUMERIC(res);
                               6304                 :                : }
                               6305                 :                : 
                               6306                 :                : Datum
                               6307                 :             87 : numeric_stddev_samp(PG_FUNCTION_ARGS)
                               6308                 :                : {
                               6309                 :                :     NumericAggState *state;
                               6310                 :                :     Numeric     res;
                               6311                 :                :     bool        is_null;
                               6312                 :                : 
 3802 tgl@sss.pgh.pa.us        6313         [ +  - ]:             87 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6314                 :                : 
                               6315                 :             87 :     res = numeric_stddev_internal(state, false, true, &is_null);
                               6316                 :                : 
 6610 neilc@samurai.com        6317         [ +  + ]:             87 :     if (is_null)
                               6318                 :             21 :         PG_RETURN_NULL();
                               6319                 :                :     else
                               6320                 :             66 :         PG_RETURN_NUMERIC(res);
                               6321                 :                : }
                               6322                 :                : 
                               6323                 :                : Datum
                               6324                 :             57 : numeric_var_pop(PG_FUNCTION_ARGS)
                               6325                 :                : {
                               6326                 :                :     NumericAggState *state;
                               6327                 :                :     Numeric     res;
                               6328                 :                :     bool        is_null;
                               6329                 :                : 
 3802 tgl@sss.pgh.pa.us        6330         [ +  - ]:             57 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6331                 :                : 
                               6332                 :             57 :     res = numeric_stddev_internal(state, true, false, &is_null);
                               6333                 :                : 
 6610 neilc@samurai.com        6334         [ -  + ]:             57 :     if (is_null)
 6610 neilc@samurai.com        6335                 :UBC           0 :         PG_RETURN_NULL();
                               6336                 :                :     else
 6610 neilc@samurai.com        6337                 :CBC          57 :         PG_RETURN_NUMERIC(res);
                               6338                 :                : }
                               6339                 :                : 
                               6340                 :                : Datum
                               6341                 :             48 : numeric_stddev_pop(PG_FUNCTION_ARGS)
                               6342                 :                : {
                               6343                 :                :     NumericAggState *state;
                               6344                 :                :     Numeric     res;
                               6345                 :                :     bool        is_null;
                               6346                 :                : 
 3802 tgl@sss.pgh.pa.us        6347         [ +  - ]:             48 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6348                 :                : 
                               6349                 :             48 :     res = numeric_stddev_internal(state, false, false, &is_null);
                               6350                 :                : 
 6610 neilc@samurai.com        6351         [ -  + ]:             48 :     if (is_null)
 6610 neilc@samurai.com        6352                 :UBC           0 :         PG_RETURN_NULL();
                               6353                 :                :     else
 6610 neilc@samurai.com        6354                 :CBC          48 :         PG_RETURN_NUMERIC(res);
                               6355                 :                : }
                               6356                 :                : 
                               6357                 :                : #ifdef HAVE_INT128
                               6358                 :                : static Numeric
 3313 andres@anarazel.de       6359                 :            211 : numeric_poly_stddev_internal(Int128AggState *state,
                               6360                 :                :                              bool variance, bool sample,
                               6361                 :                :                              bool *is_null)
                               6362                 :                : {
                               6363                 :                :     NumericAggState numstate;
                               6364                 :                :     Numeric     res;
                               6365                 :                : 
                               6366                 :                :     /* Initialize an empty agg state */
 2781 heikki.linnakangas@i     6367                 :            211 :     memset(&numstate, 0, sizeof(NumericAggState));
                               6368                 :                : 
 3313 andres@anarazel.de       6369         [ +  - ]:            211 :     if (state)
                               6370                 :                :     {
                               6371                 :                :         NumericVar  tmp_var;
                               6372                 :                : 
                               6373                 :            211 :         numstate.N = state->N;
                               6374                 :                : 
 2781 heikki.linnakangas@i     6375                 :            211 :         init_var(&tmp_var);
                               6376                 :                : 
                               6377                 :            211 :         int128_to_numericvar(state->sumX, &tmp_var);
                               6378                 :            211 :         accum_sum_add(&numstate.sumX, &tmp_var);
                               6379                 :                : 
                               6380                 :            211 :         int128_to_numericvar(state->sumX2, &tmp_var);
                               6381                 :            211 :         accum_sum_add(&numstate.sumX2, &tmp_var);
                               6382                 :                : 
                               6383                 :            211 :         free_var(&tmp_var);
                               6384                 :                :     }
                               6385                 :                : 
 3313 andres@anarazel.de       6386                 :            211 :     res = numeric_stddev_internal(&numstate, variance, sample, is_null);
                               6387                 :                : 
 2781 heikki.linnakangas@i     6388         [ +  - ]:            211 :     if (numstate.sumX.ndigits > 0)
                               6389                 :                :     {
                               6390                 :            211 :         pfree(numstate.sumX.pos_digits);
                               6391                 :            211 :         pfree(numstate.sumX.neg_digits);
                               6392                 :                :     }
                               6393         [ +  - ]:            211 :     if (numstate.sumX2.ndigits > 0)
                               6394                 :                :     {
                               6395                 :            211 :         pfree(numstate.sumX2.pos_digits);
                               6396                 :            211 :         pfree(numstate.sumX2.neg_digits);
                               6397                 :                :     }
                               6398                 :                : 
 3313 andres@anarazel.de       6399                 :            211 :     return res;
                               6400                 :                : }
                               6401                 :                : #endif
                               6402                 :                : 
                               6403                 :                : Datum
                               6404                 :             63 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
                               6405                 :                : {
                               6406                 :                : #ifdef HAVE_INT128
                               6407                 :                :     PolyNumAggState *state;
                               6408                 :                :     Numeric     res;
                               6409                 :                :     bool        is_null;
                               6410                 :                : 
                               6411         [ +  - ]:             63 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6412                 :                : 
                               6413                 :             63 :     res = numeric_poly_stddev_internal(state, true, true, &is_null);
                               6414                 :                : 
                               6415         [ +  + ]:             63 :     if (is_null)
                               6416                 :             12 :         PG_RETURN_NULL();
                               6417                 :                :     else
                               6418                 :             51 :         PG_RETURN_NUMERIC(res);
                               6419                 :                : #else
                               6420                 :                :     return numeric_var_samp(fcinfo);
                               6421                 :                : #endif
                               6422                 :                : }
                               6423                 :                : 
                               6424                 :                : Datum
                               6425                 :             82 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
                               6426                 :                : {
                               6427                 :                : #ifdef HAVE_INT128
                               6428                 :                :     PolyNumAggState *state;
                               6429                 :                :     Numeric     res;
                               6430                 :                :     bool        is_null;
                               6431                 :                : 
                               6432         [ +  - ]:             82 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6433                 :                : 
                               6434                 :             82 :     res = numeric_poly_stddev_internal(state, false, true, &is_null);
                               6435                 :                : 
                               6436         [ +  + ]:             82 :     if (is_null)
                               6437                 :             12 :         PG_RETURN_NULL();
                               6438                 :                :     else
                               6439                 :             70 :         PG_RETURN_NUMERIC(res);
                               6440                 :                : #else
                               6441                 :                :     return numeric_stddev_samp(fcinfo);
                               6442                 :                : #endif
                               6443                 :                : }
                               6444                 :                : 
                               6445                 :                : Datum
                               6446                 :             30 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
                               6447                 :                : {
                               6448                 :                : #ifdef HAVE_INT128
                               6449                 :                :     PolyNumAggState *state;
                               6450                 :                :     Numeric     res;
                               6451                 :                :     bool        is_null;
                               6452                 :                : 
                               6453         [ +  - ]:             30 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6454                 :                : 
                               6455                 :             30 :     res = numeric_poly_stddev_internal(state, true, false, &is_null);
                               6456                 :                : 
                               6457         [ -  + ]:             30 :     if (is_null)
 3313 andres@anarazel.de       6458                 :UBC           0 :         PG_RETURN_NULL();
                               6459                 :                :     else
 3313 andres@anarazel.de       6460                 :CBC          30 :         PG_RETURN_NUMERIC(res);
                               6461                 :                : #else
                               6462                 :                :     return numeric_var_pop(fcinfo);
                               6463                 :                : #endif
                               6464                 :                : }
                               6465                 :                : 
                               6466                 :                : Datum
                               6467                 :             36 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
                               6468                 :                : {
                               6469                 :                : #ifdef HAVE_INT128
                               6470                 :                :     PolyNumAggState *state;
                               6471                 :                :     Numeric     res;
                               6472                 :                :     bool        is_null;
                               6473                 :                : 
                               6474         [ +  - ]:             36 :     state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
                               6475                 :                : 
                               6476                 :             36 :     res = numeric_poly_stddev_internal(state, false, false, &is_null);
                               6477                 :                : 
                               6478         [ -  + ]:             36 :     if (is_null)
 3313 andres@anarazel.de       6479                 :UBC           0 :         PG_RETURN_NULL();
                               6480                 :                :     else
 3313 andres@anarazel.de       6481                 :CBC          36 :         PG_RETURN_NUMERIC(res);
                               6482                 :                : #else
                               6483                 :                :     return numeric_stddev_pop(fcinfo);
                               6484                 :                : #endif
                               6485                 :                : }
                               6486                 :                : 
                               6487                 :                : /*
                               6488                 :                :  * SUM transition functions for integer datatypes.
                               6489                 :                :  *
                               6490                 :                :  * To avoid overflow, we use accumulators wider than the input datatype.
                               6491                 :                :  * A Numeric accumulator is needed for int8 input; for int4 and int2
                               6492                 :                :  * inputs, we use int8 accumulators which should be sufficient for practical
                               6493                 :                :  * purposes.  (The latter two therefore don't really belong in this file,
                               6494                 :                :  * but we keep them here anyway.)
                               6495                 :                :  *
                               6496                 :                :  * Because SQL defines the SUM() of no values to be NULL, not zero,
                               6497                 :                :  * the initial condition of the transition data value needs to be NULL. This
                               6498                 :                :  * means we can't rely on ExecAgg to automatically insert the first non-null
                               6499                 :                :  * data value into the transition data: it doesn't know how to do the type
                               6500                 :                :  * conversion.  The upshot is that these routines have to be marked non-strict
                               6501                 :                :  * and handle substitution of the first non-null input themselves.
                               6502                 :                :  *
                               6503                 :                :  * Note: these functions are used only in plain aggregation mode.
                               6504                 :                :  * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
                               6505                 :                :  */
                               6506                 :                : 
                               6507                 :                : Datum
 8672 tgl@sss.pgh.pa.us        6508                 :             12 : int2_sum(PG_FUNCTION_ARGS)
                               6509                 :                : {
                               6510                 :                :     int64       newval;
                               6511                 :                : 
                               6512         [ +  + ]:             12 :     if (PG_ARGISNULL(0))
                               6513                 :                :     {
                               6514                 :                :         /* No non-null input seen so far... */
                               6515         [ -  + ]:              3 :         if (PG_ARGISNULL(1))
 8672 tgl@sss.pgh.pa.us        6516                 :UBC           0 :             PG_RETURN_NULL();   /* still no non-null */
                               6517                 :                :         /* This is the first non-null input. */
 8279 tgl@sss.pgh.pa.us        6518                 :CBC           3 :         newval = (int64) PG_GETARG_INT16(1);
                               6519                 :              3 :         PG_RETURN_INT64(newval);
                               6520                 :                :     }
                               6521                 :                : 
                               6522                 :                :     /*
                               6523                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6524                 :                :      * parameter in-place to avoid palloc overhead. If not, we need to return
                               6525                 :                :      * the new value of the transition variable. (If int8 is pass-by-value,
                               6526                 :                :      * then of course this is useless as well as incorrect, so just ifdef it
                               6527                 :                :      * out.)
                               6528                 :                :      */
                               6529                 :                : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
                               6530                 :                :     if (AggCheckCallContext(fcinfo, NULL))
                               6531                 :                :     {
                               6532                 :                :         int64      *oldsum = (int64 *) PG_GETARG_POINTER(0);
                               6533                 :                : 
                               6534                 :                :         /* Leave the running sum unchanged in the new input is null */
                               6535                 :                :         if (!PG_ARGISNULL(1))
                               6536                 :                :             *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
                               6537                 :                : 
                               6538                 :                :         PG_RETURN_POINTER(oldsum);
                               6539                 :                :     }
                               6540                 :                :     else
                               6541                 :                : #endif
                               6542                 :                :     {
 6948 neilc@samurai.com        6543                 :              9 :         int64       oldsum = PG_GETARG_INT64(0);
                               6544                 :                : 
                               6545                 :                :         /* Leave sum unchanged if new input is null. */
                               6546         [ -  + ]:              9 :         if (PG_ARGISNULL(1))
 6948 neilc@samurai.com        6547                 :UBC           0 :             PG_RETURN_INT64(oldsum);
                               6548                 :                : 
                               6549                 :                :         /* OK to do the addition. */
 6948 neilc@samurai.com        6550                 :CBC           9 :         newval = oldsum + (int64) PG_GETARG_INT16(1);
                               6551                 :                : 
                               6552                 :              9 :         PG_RETURN_INT64(newval);
                               6553                 :                :     }
                               6554                 :                : }
                               6555                 :                : 
                               6556                 :                : Datum
 8672 tgl@sss.pgh.pa.us        6557                 :        1789030 : int4_sum(PG_FUNCTION_ARGS)
                               6558                 :                : {
                               6559                 :                :     int64       newval;
                               6560                 :                : 
                               6561         [ +  + ]:        1789030 :     if (PG_ARGISNULL(0))
                               6562                 :                :     {
                               6563                 :                :         /* No non-null input seen so far... */
                               6564         [ +  + ]:         103689 :         if (PG_ARGISNULL(1))
                               6565                 :            493 :             PG_RETURN_NULL();   /* still no non-null */
                               6566                 :                :         /* This is the first non-null input. */
 8279                          6567                 :         103196 :         newval = (int64) PG_GETARG_INT32(1);
                               6568                 :         103196 :         PG_RETURN_INT64(newval);
                               6569                 :                :     }
                               6570                 :                : 
                               6571                 :                :     /*
                               6572                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6573                 :                :      * parameter in-place to avoid palloc overhead. If not, we need to return
                               6574                 :                :      * the new value of the transition variable. (If int8 is pass-by-value,
                               6575                 :                :      * then of course this is useless as well as incorrect, so just ifdef it
                               6576                 :                :      * out.)
                               6577                 :                :      */
                               6578                 :                : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
                               6579                 :                :     if (AggCheckCallContext(fcinfo, NULL))
                               6580                 :                :     {
                               6581                 :                :         int64      *oldsum = (int64 *) PG_GETARG_POINTER(0);
                               6582                 :                : 
                               6583                 :                :         /* Leave the running sum unchanged in the new input is null */
                               6584                 :                :         if (!PG_ARGISNULL(1))
                               6585                 :                :             *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
                               6586                 :                : 
                               6587                 :                :         PG_RETURN_POINTER(oldsum);
                               6588                 :                :     }
                               6589                 :                :     else
                               6590                 :                : #endif
                               6591                 :                :     {
 6948 neilc@samurai.com        6592                 :        1685341 :         int64       oldsum = PG_GETARG_INT64(0);
                               6593                 :                : 
                               6594                 :                :         /* Leave sum unchanged if new input is null. */
                               6595         [ +  + ]:        1685341 :         if (PG_ARGISNULL(1))
                               6596                 :            437 :             PG_RETURN_INT64(oldsum);
                               6597                 :                : 
                               6598                 :                :         /* OK to do the addition. */
                               6599                 :        1684904 :         newval = oldsum + (int64) PG_GETARG_INT32(1);
                               6600                 :                : 
                               6601                 :        1684904 :         PG_RETURN_INT64(newval);
                               6602                 :                :     }
                               6603                 :                : }
                               6604                 :                : 
                               6605                 :                : /*
                               6606                 :                :  * Note: this function is obsolete, it's no longer used for SUM(int8).
                               6607                 :                :  */
                               6608                 :                : Datum
 8672 tgl@sss.pgh.pa.us        6609                 :UBC           0 : int8_sum(PG_FUNCTION_ARGS)
                               6610                 :                : {
                               6611                 :                :     Numeric     oldsum;
                               6612                 :                : 
                               6613         [ #  # ]:              0 :     if (PG_ARGISNULL(0))
                               6614                 :                :     {
                               6615                 :                :         /* No non-null input seen so far... */
                               6616         [ #  # ]:              0 :         if (PG_ARGISNULL(1))
                               6617                 :              0 :             PG_RETURN_NULL();   /* still no non-null */
                               6618                 :                :         /* This is the first non-null input. */
 1313 peter@eisentraut.org     6619                 :              0 :         PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
                               6620                 :                :     }
                               6621                 :                : 
                               6622                 :                :     /*
                               6623                 :                :      * Note that we cannot special-case the aggregate case here, as we do for
                               6624                 :                :      * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
                               6625                 :                :      * our first parameter in-place.
                               6626                 :                :      */
                               6627                 :                : 
 8672 tgl@sss.pgh.pa.us        6628                 :              0 :     oldsum = PG_GETARG_NUMERIC(0);
                               6629                 :                : 
                               6630                 :                :     /* Leave sum unchanged if new input is null. */
                               6631         [ #  # ]:              0 :     if (PG_ARGISNULL(1))
                               6632                 :              0 :         PG_RETURN_NUMERIC(oldsum);
                               6633                 :                : 
                               6634                 :                :     /* OK to do the addition. */
 8660                          6635                 :              0 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
                               6636                 :                :                                         NumericGetDatum(oldsum),
                               6637                 :                :                                         NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
                               6638                 :                : }
                               6639                 :                : 
                               6640                 :                : 
                               6641                 :                : /*
                               6642                 :                :  * Routines for avg(int2) and avg(int4).  The transition datatype
                               6643                 :                :  * is a two-element int8 array, holding count and sum.
                               6644                 :                :  *
                               6645                 :                :  * These functions are also used for sum(int2) and sum(int4) when
                               6646                 :                :  * operating in moving-aggregate mode, since for correct inverse transitions
                               6647                 :                :  * we need to count the inputs.
                               6648                 :                :  */
                               6649                 :                : 
                               6650                 :                : typedef struct Int8TransTypeData
                               6651                 :                : {
                               6652                 :                :     int64       count;
                               6653                 :                :     int64       sum;
                               6654                 :                : } Int8TransTypeData;
                               6655                 :                : 
                               6656                 :                : Datum
 8279 tgl@sss.pgh.pa.us        6657                 :CBC          21 : int2_avg_accum(PG_FUNCTION_ARGS)
                               6658                 :                : {
                               6659                 :                :     ArrayType  *transarray;
                               6660                 :             21 :     int16       newval = PG_GETARG_INT16(1);
                               6661                 :                :     Int8TransTypeData *transdata;
                               6662                 :                : 
                               6663                 :                :     /*
                               6664                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6665                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6666                 :                :      * a copy of it before scribbling on it.
                               6667                 :                :      */
 5179                          6668         [ +  - ]:             21 :     if (AggCheckCallContext(fcinfo, NULL))
 6950 neilc@samurai.com        6669                 :             21 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6670                 :                :     else
 6950 neilc@samurai.com        6671                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6672                 :                : 
 6723 tgl@sss.pgh.pa.us        6673         [ +  - ]:CBC          21 :     if (ARR_HASNULL(transarray) ||
                               6674         [ -  + ]:             21 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 7567 tgl@sss.pgh.pa.us        6675         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6676                 :                : 
 6950 neilc@samurai.com        6677         [ -  + ]:CBC          21 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
 8279 tgl@sss.pgh.pa.us        6678                 :             21 :     transdata->count++;
                               6679                 :             21 :     transdata->sum += newval;
                               6680                 :                : 
                               6681                 :             21 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6682                 :                : }
                               6683                 :                : 
                               6684                 :                : Datum
                               6685                 :        1298151 : int4_avg_accum(PG_FUNCTION_ARGS)
                               6686                 :                : {
                               6687                 :                :     ArrayType  *transarray;
                               6688                 :        1298151 :     int32       newval = PG_GETARG_INT32(1);
                               6689                 :                :     Int8TransTypeData *transdata;
                               6690                 :                : 
                               6691                 :                :     /*
                               6692                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6693                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6694                 :                :      * a copy of it before scribbling on it.
                               6695                 :                :      */
 5179                          6696         [ +  - ]:        1298151 :     if (AggCheckCallContext(fcinfo, NULL))
 6950 neilc@samurai.com        6697                 :        1298151 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6698                 :                :     else
 6950 neilc@samurai.com        6699                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6700                 :                : 
 6723 tgl@sss.pgh.pa.us        6701         [ +  - ]:CBC     1298151 :     if (ARR_HASNULL(transarray) ||
                               6702         [ -  + ]:        1298151 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 7567 tgl@sss.pgh.pa.us        6703         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6704                 :                : 
 6950 neilc@samurai.com        6705         [ -  + ]:CBC     1298151 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
 8279 tgl@sss.pgh.pa.us        6706                 :        1298151 :     transdata->count++;
                               6707                 :        1298151 :     transdata->sum += newval;
                               6708                 :                : 
                               6709                 :        1298151 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6710                 :                : }
                               6711                 :                : 
                               6712                 :                : Datum
 2931 rhaas@postgresql.org     6713                 :           2201 : int4_avg_combine(PG_FUNCTION_ARGS)
                               6714                 :                : {
                               6715                 :                :     ArrayType  *transarray1;
                               6716                 :                :     ArrayType  *transarray2;
                               6717                 :                :     Int8TransTypeData *state1;
                               6718                 :                :     Int8TransTypeData *state2;
                               6719                 :                : 
                               6720         [ -  + ]:           2201 :     if (!AggCheckCallContext(fcinfo, NULL))
 2931 rhaas@postgresql.org     6721         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               6722                 :                : 
 2931 rhaas@postgresql.org     6723                 :CBC        2201 :     transarray1 = PG_GETARG_ARRAYTYPE_P(0);
                               6724                 :           2201 :     transarray2 = PG_GETARG_ARRAYTYPE_P(1);
                               6725                 :                : 
                               6726         [ +  - ]:           2201 :     if (ARR_HASNULL(transarray1) ||
                               6727         [ -  + ]:           2201 :         ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 2931 rhaas@postgresql.org     6728         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6729                 :                : 
 2931 rhaas@postgresql.org     6730         [ +  - ]:CBC        2201 :     if (ARR_HASNULL(transarray2) ||
                               6731         [ -  + ]:           2201 :         ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 2931 rhaas@postgresql.org     6732         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6733                 :                : 
 2931 rhaas@postgresql.org     6734         [ -  + ]:CBC        2201 :     state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
                               6735         [ -  + ]:           2201 :     state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
                               6736                 :                : 
                               6737                 :           2201 :     state1->count += state2->count;
                               6738                 :           2201 :     state1->sum += state2->sum;
                               6739                 :                : 
                               6740                 :           2201 :     PG_RETURN_ARRAYTYPE_P(transarray1);
                               6741                 :                : }
                               6742                 :                : 
                               6743                 :                : Datum
 3655 tgl@sss.pgh.pa.us        6744                 :              6 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
                               6745                 :                : {
                               6746                 :                :     ArrayType  *transarray;
                               6747                 :              6 :     int16       newval = PG_GETARG_INT16(1);
                               6748                 :                :     Int8TransTypeData *transdata;
                               6749                 :                : 
                               6750                 :                :     /*
                               6751                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6752                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6753                 :                :      * a copy of it before scribbling on it.
                               6754                 :                :      */
                               6755         [ +  - ]:              6 :     if (AggCheckCallContext(fcinfo, NULL))
                               6756                 :              6 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6757                 :                :     else
 3655 tgl@sss.pgh.pa.us        6758                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6759                 :                : 
 3655 tgl@sss.pgh.pa.us        6760         [ +  - ]:CBC           6 :     if (ARR_HASNULL(transarray) ||
                               6761         [ -  + ]:              6 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 3655 tgl@sss.pgh.pa.us        6762         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6763                 :                : 
 3655 tgl@sss.pgh.pa.us        6764         [ -  + ]:CBC           6 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6765                 :              6 :     transdata->count--;
                               6766                 :              6 :     transdata->sum -= newval;
                               6767                 :                : 
                               6768                 :              6 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6769                 :                : }
                               6770                 :                : 
                               6771                 :                : Datum
                               6772                 :            726 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
                               6773                 :                : {
                               6774                 :                :     ArrayType  *transarray;
                               6775                 :            726 :     int32       newval = PG_GETARG_INT32(1);
                               6776                 :                :     Int8TransTypeData *transdata;
                               6777                 :                : 
                               6778                 :                :     /*
                               6779                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6780                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6781                 :                :      * a copy of it before scribbling on it.
                               6782                 :                :      */
                               6783         [ +  - ]:            726 :     if (AggCheckCallContext(fcinfo, NULL))
                               6784                 :            726 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6785                 :                :     else
 3655 tgl@sss.pgh.pa.us        6786                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6787                 :                : 
 3655 tgl@sss.pgh.pa.us        6788         [ +  - ]:CBC         726 :     if (ARR_HASNULL(transarray) ||
                               6789         [ -  + ]:            726 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 3655 tgl@sss.pgh.pa.us        6790         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6791                 :                : 
 3655 tgl@sss.pgh.pa.us        6792         [ -  + ]:CBC         726 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6793                 :            726 :     transdata->count--;
                               6794                 :            726 :     transdata->sum -= newval;
                               6795                 :                : 
                               6796                 :            726 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6797                 :                : }
                               6798                 :                : 
                               6799                 :                : Datum
 8279                          6800                 :           5375 : int8_avg(PG_FUNCTION_ARGS)
                               6801                 :                : {
                               6802                 :           5375 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6803                 :                :     Int8TransTypeData *transdata;
                               6804                 :                :     Datum       countd,
                               6805                 :                :                 sumd;
                               6806                 :                : 
 6723                          6807         [ +  - ]:           5375 :     if (ARR_HASNULL(transarray) ||
                               6808         [ -  + ]:           5375 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 7567 tgl@sss.pgh.pa.us        6809         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
 8279 tgl@sss.pgh.pa.us        6810         [ -  + ]:CBC        5375 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6811                 :                : 
                               6812                 :                :     /* SQL defines AVG of no values to be NULL */
                               6813         [ +  + ]:           5375 :     if (transdata->count == 0)
                               6814                 :             59 :         PG_RETURN_NULL();
                               6815                 :                : 
 1313 peter@eisentraut.org     6816                 :           5316 :     countd = NumericGetDatum(int64_to_numeric(transdata->count));
                               6817                 :           5316 :     sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
                               6818                 :                : 
 8279 tgl@sss.pgh.pa.us        6819                 :           5316 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
                               6820                 :                : }
                               6821                 :                : 
                               6822                 :                : /*
                               6823                 :                :  * SUM(int2) and SUM(int4) both return int8, so we can use this
                               6824                 :                :  * final function for both.
                               6825                 :                :  */
                               6826                 :                : Datum
 3655                          6827                 :           1917 : int2int4_sum(PG_FUNCTION_ARGS)
                               6828                 :                : {
                               6829                 :           1917 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6830                 :                :     Int8TransTypeData *transdata;
                               6831                 :                : 
                               6832         [ +  - ]:           1917 :     if (ARR_HASNULL(transarray) ||
                               6833         [ -  + ]:           1917 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 3655 tgl@sss.pgh.pa.us        6834         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
 3655 tgl@sss.pgh.pa.us        6835         [ -  + ]:CBC        1917 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6836                 :                : 
                               6837                 :                :     /* SQL defines SUM of no values to be NULL */
                               6838         [ +  + ]:           1917 :     if (transdata->count == 0)
                               6839                 :            240 :         PG_RETURN_NULL();
                               6840                 :                : 
                               6841                 :           1677 :     PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
                               6842                 :                : }
                               6843                 :                : 
                               6844                 :                : 
                               6845                 :                : /* ----------------------------------------------------------------------
                               6846                 :                :  *
                               6847                 :                :  * Debug support
                               6848                 :                :  *
                               6849                 :                :  * ----------------------------------------------------------------------
                               6850                 :                :  */
                               6851                 :                : 
                               6852                 :                : #ifdef NUMERIC_DEBUG
                               6853                 :                : 
                               6854                 :                : /*
                               6855                 :                :  * dump_numeric() - Dump a value in the db storage format for debugging
                               6856                 :                :  */
                               6857                 :                : static void
                               6858                 :                : dump_numeric(const char *str, Numeric num)
                               6859                 :                : {
                               6860                 :                :     NumericDigit *digits = NUMERIC_DIGITS(num);
                               6861                 :                :     int         ndigits;
                               6862                 :                :     int         i;
                               6863                 :                : 
                               6864                 :                :     ndigits = NUMERIC_NDIGITS(num);
                               6865                 :                : 
                               6866                 :                :     printf("%s: NUMERIC w=%d d=%d ", str,
                               6867                 :                :            NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
                               6868                 :                :     switch (NUMERIC_SIGN(num))
                               6869                 :                :     {
                               6870                 :                :         case NUMERIC_POS:
                               6871                 :                :             printf("POS");
                               6872                 :                :             break;
                               6873                 :                :         case NUMERIC_NEG:
                               6874                 :                :             printf("NEG");
                               6875                 :                :             break;
                               6876                 :                :         case NUMERIC_NAN:
                               6877                 :                :             printf("NaN");
                               6878                 :                :             break;
                               6879                 :                :         case NUMERIC_PINF:
                               6880                 :                :             printf("Infinity");
                               6881                 :                :             break;
                               6882                 :                :         case NUMERIC_NINF:
                               6883                 :                :             printf("-Infinity");
                               6884                 :                :             break;
                               6885                 :                :         default:
                               6886                 :                :             printf("SIGN=0x%x", NUMERIC_SIGN(num));
                               6887                 :                :             break;
                               6888                 :                :     }
                               6889                 :                : 
                               6890                 :                :     for (i = 0; i < ndigits; i++)
                               6891                 :                :         printf(" %0*d", DEC_DIGITS, digits[i]);
                               6892                 :                :     printf("\n");
                               6893                 :                : }
                               6894                 :                : 
                               6895                 :                : 
                               6896                 :                : /*
                               6897                 :                :  * dump_var() - Dump a value in the variable format for debugging
                               6898                 :                :  */
                               6899                 :                : static void
                               6900                 :                : dump_var(const char *str, NumericVar *var)
                               6901                 :                : {
                               6902                 :                :     int         i;
                               6903                 :                : 
                               6904                 :                :     printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
                               6905                 :                :     switch (var->sign)
                               6906                 :                :     {
                               6907                 :                :         case NUMERIC_POS:
                               6908                 :                :             printf("POS");
                               6909                 :                :             break;
                               6910                 :                :         case NUMERIC_NEG:
                               6911                 :                :             printf("NEG");
                               6912                 :                :             break;
                               6913                 :                :         case NUMERIC_NAN:
                               6914                 :                :             printf("NaN");
                               6915                 :                :             break;
                               6916                 :                :         case NUMERIC_PINF:
                               6917                 :                :             printf("Infinity");
                               6918                 :                :             break;
                               6919                 :                :         case NUMERIC_NINF:
                               6920                 :                :             printf("-Infinity");
                               6921                 :                :             break;
                               6922                 :                :         default:
                               6923                 :                :             printf("SIGN=0x%x", var->sign);
                               6924                 :                :             break;
                               6925                 :                :     }
                               6926                 :                : 
                               6927                 :                :     for (i = 0; i < var->ndigits; i++)
                               6928                 :                :         printf(" %0*d", DEC_DIGITS, var->digits[i]);
                               6929                 :                : 
                               6930                 :                :     printf("\n");
                               6931                 :                : }
                               6932                 :                : #endif                          /* NUMERIC_DEBUG */
                               6933                 :                : 
                               6934                 :                : 
                               6935                 :                : /* ----------------------------------------------------------------------
                               6936                 :                :  *
                               6937                 :                :  * Local functions follow
                               6938                 :                :  *
                               6939                 :                :  * In general, these do not support "special" (NaN or infinity) inputs;
                               6940                 :                :  * callers should handle those possibilities first.
                               6941                 :                :  * (There are one or two exceptions, noted in their header comments.)
                               6942                 :                :  *
                               6943                 :                :  * ----------------------------------------------------------------------
                               6944                 :                :  */
                               6945                 :                : 
                               6946                 :                : 
                               6947                 :                : /*
                               6948                 :                :  * alloc_var() -
                               6949                 :                :  *
                               6950                 :                :  *  Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
                               6951                 :                :  */
                               6952                 :                : static void
 8853                          6953                 :        1452120 : alloc_var(NumericVar *var, int ndigits)
                               6954                 :                : {
                               6955         [ +  + ]:        1452120 :     digitbuf_free(var->buf);
                               6956                 :        1452120 :     var->buf = digitbuf_alloc(ndigits + 1);
 7559 bruce@momjian.us         6957                 :        1452120 :     var->buf[0] = 0;         /* spare digit for rounding */
 8853 tgl@sss.pgh.pa.us        6958                 :        1452120 :     var->digits = var->buf + 1;
                               6959                 :        1452120 :     var->ndigits = ndigits;
 9237 JanWieck@Yahoo.com       6960                 :        1452120 : }
                               6961                 :                : 
                               6962                 :                : 
                               6963                 :                : /*
                               6964                 :                :  * free_var() -
                               6965                 :                :  *
                               6966                 :                :  *  Return the digit buffer of a variable to the free pool
                               6967                 :                :  */
                               6968                 :                : static void
 9091 bruce@momjian.us         6969                 :        1706634 : free_var(NumericVar *var)
                               6970                 :                : {
 8853 tgl@sss.pgh.pa.us        6971         [ +  + ]:        1706634 :     digitbuf_free(var->buf);
                               6972                 :        1706634 :     var->buf = NULL;
                               6973                 :        1706634 :     var->digits = NULL;
 9237 JanWieck@Yahoo.com       6974                 :        1706634 :     var->sign = NUMERIC_NAN;
                               6975                 :        1706634 : }
                               6976                 :                : 
                               6977                 :                : 
                               6978                 :                : /*
                               6979                 :                :  * zero_var() -
                               6980                 :                :  *
                               6981                 :                :  *  Set a variable to ZERO.
                               6982                 :                :  *  Note: its dscale is not touched.
                               6983                 :                :  */
                               6984                 :                : static void
 8853 tgl@sss.pgh.pa.us        6985                 :          20268 : zero_var(NumericVar *var)
                               6986                 :                : {
                               6987         [ +  + ]:          20268 :     digitbuf_free(var->buf);
                               6988                 :          20268 :     var->buf = NULL;
                               6989                 :          20268 :     var->digits = NULL;
                               6990                 :          20268 :     var->ndigits = 0;
                               6991                 :          20268 :     var->weight = 0;         /* by convention; doesn't really matter */
                               6992                 :          20268 :     var->sign = NUMERIC_POS; /* anything but NAN... */
 9237 JanWieck@Yahoo.com       6993                 :          20268 : }
                               6994                 :                : 
                               6995                 :                : 
                               6996                 :                : /*
                               6997                 :                :  * set_var_from_str()
                               6998                 :                :  *
                               6999                 :                :  *  Parse a string and put the number into a variable
                               7000                 :                :  *
                               7001                 :                :  * This function does not handle leading or trailing spaces.  It returns
                               7002                 :                :  * the end+1 position parsed into *endptr, so that caller can check for
                               7003                 :                :  * trailing spaces/garbage if deemed necessary.
                               7004                 :                :  *
                               7005                 :                :  * cp is the place to actually start parsing; str is what to use in error
                               7006                 :                :  * reports.  (Typically cp would be the same except advanced over spaces.)
                               7007                 :                :  *
                               7008                 :                :  * Returns true on success, false on failure (if escontext points to an
                               7009                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               7010                 :                :  */
                               7011                 :                : static bool
  492 tgl@sss.pgh.pa.us        7012                 :          63797 : set_var_from_str(const char *str, const char *cp,
                               7013                 :                :                  NumericVar *dest, const char **endptr,
                               7014                 :                :                  Node *escontext)
                               7015                 :                : {
 2433 peter_e@gmx.net          7016                 :          63797 :     bool        have_dp = false;
                               7017                 :                :     int         i;
                               7018                 :                :     unsigned char *decdigits;
 7695 tgl@sss.pgh.pa.us        7019                 :          63797 :     int         sign = NUMERIC_POS;
                               7020                 :          63797 :     int         dweight = -1;
                               7021                 :                :     int         ddigits;
                               7022                 :          63797 :     int         dscale = 0;
                               7023                 :                :     int         weight;
                               7024                 :                :     int         ndigits;
                               7025                 :                :     int         offset;
                               7026                 :                :     NumericDigit *digits;
                               7027                 :                : 
                               7028                 :                :     /*
                               7029                 :                :      * We first parse the string to extract decimal digits and determine the
                               7030                 :                :      * correct decimal weight.  Then convert to NBASE representation.
                               7031                 :                :      */
 9237 JanWieck@Yahoo.com       7032      [ -  +  + ]:          63797 :     switch (*cp)
                               7033                 :                :     {
 9091 bruce@momjian.us         7034                 :UBC           0 :         case '+':
 7695 tgl@sss.pgh.pa.us        7035                 :              0 :             sign = NUMERIC_POS;
 9091 bruce@momjian.us         7036                 :              0 :             cp++;
                               7037                 :              0 :             break;
                               7038                 :                : 
 9091 bruce@momjian.us         7039                 :CBC         150 :         case '-':
 7695 tgl@sss.pgh.pa.us        7040                 :            150 :             sign = NUMERIC_NEG;
 9091 bruce@momjian.us         7041                 :            150 :             cp++;
                               7042                 :            150 :             break;
                               7043                 :                :     }
                               7044                 :                : 
 9237 JanWieck@Yahoo.com       7045         [ +  + ]:          63797 :     if (*cp == '.')
                               7046                 :                :     {
 2433 peter_e@gmx.net          7047                 :            191 :         have_dp = true;
 9237 JanWieck@Yahoo.com       7048                 :            191 :         cp++;
                               7049                 :                :     }
                               7050                 :                : 
 8533 tgl@sss.pgh.pa.us        7051         [ -  + ]:          63797 :     if (!isdigit((unsigned char) *cp))
  435 dean.a.rasheed@gmail     7052                 :UBC           0 :         goto invalid_syntax;
                               7053                 :                : 
 7559 bruce@momjian.us         7054                 :CBC       63797 :     decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
                               7055                 :                : 
                               7056                 :                :     /* leading padding for digit alignment later */
 7695 tgl@sss.pgh.pa.us        7057                 :          63797 :     memset(decdigits, 0, DEC_DIGITS);
                               7058                 :          63797 :     i = DEC_DIGITS;
                               7059                 :                : 
 9237 JanWieck@Yahoo.com       7060         [ +  + ]:         261405 :     while (*cp)
                               7061                 :                :     {
 8533 tgl@sss.pgh.pa.us        7062         [ +  + ]:         198181 :         if (isdigit((unsigned char) *cp))
                               7063                 :                :         {
 7695                          7064                 :         189464 :             decdigits[i++] = *cp++ - '0';
 8853                          7065         [ +  + ]:         189464 :             if (!have_dp)
 7695                          7066                 :         153742 :                 dweight++;
                               7067                 :                :             else
                               7068                 :          35722 :                 dscale++;
                               7069                 :                :         }
 8853                          7070         [ +  + ]:           8717 :         else if (*cp == '.')
                               7071                 :                :         {
                               7072         [ -  + ]:           8063 :             if (have_dp)
  435 dean.a.rasheed@gmail     7073                 :UBC           0 :                 goto invalid_syntax;
 2433 peter_e@gmx.net          7074                 :CBC        8063 :             have_dp = true;
 8853 tgl@sss.pgh.pa.us        7075                 :           8063 :             cp++;
                               7076                 :                :             /* decimal point must not be followed by underscore */
  435 dean.a.rasheed@gmail     7077         [ +  + ]:           8063 :             if (*cp == '_')
                               7078                 :              3 :                 goto invalid_syntax;
                               7079                 :                :         }
                               7080         [ +  + ]:            654 :         else if (*cp == '_')
                               7081                 :                :         {
                               7082                 :                :             /* underscore must be followed by more digits */
                               7083                 :             93 :             cp++;
                               7084         [ +  + ]:             93 :             if (!isdigit((unsigned char) *cp))
                               7085                 :              9 :                 goto invalid_syntax;
                               7086                 :                :         }
                               7087                 :                :         else
 8853 tgl@sss.pgh.pa.us        7088                 :            561 :             break;
                               7089                 :                :     }
                               7090                 :                : 
 7695                          7091                 :          63785 :     ddigits = i - DEC_DIGITS;
                               7092                 :                :     /* trailing padding for digit alignment later */
 7559 bruce@momjian.us         7093                 :          63785 :     memset(decdigits + i, 0, DEC_DIGITS - 1);
                               7094                 :                : 
                               7095                 :                :     /* Handle exponent, if any */
 9237 JanWieck@Yahoo.com       7096   [ +  +  +  + ]:          63785 :     if (*cp == 'e' || *cp == 'E')
                               7097                 :                :     {
  435 dean.a.rasheed@gmail     7098                 :            537 :         int64       exponent = 0;
                               7099                 :            537 :         bool        neg = false;
                               7100                 :                : 
                               7101                 :                :         /*
                               7102                 :                :          * At this point, dweight and dscale can't be more than about
                               7103                 :                :          * INT_MAX/2 due to the MaxAllocSize limit on string length, so
                               7104                 :                :          * constraining the exponent similarly should be enough to prevent
                               7105                 :                :          * integer overflow in this function.  If the value is too large to
                               7106                 :                :          * fit in storage format, make_result() will complain about it later;
                               7107                 :                :          * for consistency use the same ereport errcode/text as make_result().
                               7108                 :                :          */
                               7109                 :                : 
                               7110                 :                :         /* exponent sign */
                               7111                 :            537 :         cp++;
                               7112         [ +  + ]:            537 :         if (*cp == '+')
                               7113                 :             77 :             cp++;
                               7114         [ +  + ]:            460 :         else if (*cp == '-')
                               7115                 :                :         {
                               7116                 :            196 :             neg = true;
                               7117                 :            196 :             cp++;
                               7118                 :                :         }
                               7119                 :                : 
                               7120                 :                :         /* exponent digits */
                               7121         [ +  + ]:            537 :         if (!isdigit((unsigned char) *cp))
                               7122                 :              3 :             goto invalid_syntax;
                               7123                 :                : 
                               7124         [ +  + ]:           1662 :         while (*cp)
                               7125                 :                :         {
                               7126         [ +  + ]:           1137 :             if (isdigit((unsigned char) *cp))
                               7127                 :                :             {
                               7128                 :           1116 :                 exponent = exponent * 10 + (*cp++ - '0');
                               7129         [ +  + ]:           1116 :                 if (exponent > PG_INT32_MAX / 2)
                               7130                 :              3 :                     goto out_of_range;
                               7131                 :                :             }
                               7132         [ +  - ]:             21 :             else if (*cp == '_')
                               7133                 :                :             {
                               7134                 :                :                 /* underscore must be followed by more digits */
                               7135                 :             21 :                 cp++;
                               7136         [ +  + ]:             21 :                 if (!isdigit((unsigned char) *cp))
                               7137                 :              6 :                     goto invalid_syntax;
                               7138                 :                :             }
                               7139                 :                :             else
  435 dean.a.rasheed@gmail     7140                 :UBC           0 :                 break;
                               7141                 :                :         }
                               7142                 :                : 
  435 dean.a.rasheed@gmail     7143         [ +  + ]:CBC         525 :         if (neg)
                               7144                 :            196 :             exponent = -exponent;
                               7145                 :                : 
 7695 tgl@sss.pgh.pa.us        7146                 :            525 :         dweight += (int) exponent;
                               7147                 :            525 :         dscale -= (int) exponent;
                               7148         [ +  + ]:            525 :         if (dscale < 0)
                               7149                 :            227 :             dscale = 0;
                               7150                 :                :     }
                               7151                 :                : 
                               7152                 :                :     /*
                               7153                 :                :      * Okay, convert pure-decimal representation to base NBASE.  First we need
                               7154                 :                :      * to determine the converted weight and ndigits.  offset is the number of
                               7155                 :                :      * decimal zeroes to insert before the first given digit to have a
                               7156                 :                :      * correctly aligned first NBASE digit.
                               7157                 :                :      */
                               7158         [ +  + ]:          63773 :     if (dweight >= 0)
 7559 bruce@momjian.us         7159                 :          63437 :         weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
                               7160                 :                :     else
                               7161                 :            336 :         weight = -((-dweight - 1) / DEC_DIGITS + 1);
 7695 tgl@sss.pgh.pa.us        7162                 :          63773 :     offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
 7559 bruce@momjian.us         7163                 :          63773 :     ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
                               7164                 :                : 
 7695 tgl@sss.pgh.pa.us        7165                 :          63773 :     alloc_var(dest, ndigits);
                               7166                 :          63773 :     dest->sign = sign;
                               7167                 :          63773 :     dest->weight = weight;
                               7168                 :          63773 :     dest->dscale = dscale;
                               7169                 :                : 
                               7170                 :          63773 :     i = DEC_DIGITS - offset;
                               7171                 :          63773 :     digits = dest->digits;
                               7172                 :                : 
                               7173         [ +  + ]:         150374 :     while (ndigits-- > 0)
                               7174                 :                :     {
                               7175                 :                : #if DEC_DIGITS == 4
 7559 bruce@momjian.us         7176                 :          86601 :         *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
                               7177                 :          86601 :                      decdigits[i + 2]) * 10 + decdigits[i + 3];
                               7178                 :                : #elif DEC_DIGITS == 2
                               7179                 :                :         *digits++ = decdigits[i] * 10 + decdigits[i + 1];
                               7180                 :                : #elif DEC_DIGITS == 1
                               7181                 :                :         *digits++ = decdigits[i];
                               7182                 :                : #else
                               7183                 :                : #error unsupported NBASE
                               7184                 :                : #endif
 7695 tgl@sss.pgh.pa.us        7185                 :          86601 :         i += DEC_DIGITS;
                               7186                 :                :     }
                               7187                 :                : 
                               7188                 :          63773 :     pfree(decdigits);
                               7189                 :                : 
                               7190                 :                :     /* Strip any leading/trailing zeroes, and normalize weight if zero */
                               7191                 :          63773 :     strip_var(dest);
                               7192                 :                : 
                               7193                 :                :     /* Return end+1 position for caller */
  492                          7194                 :          63773 :     *endptr = cp;
                               7195                 :                : 
                               7196                 :          63773 :     return true;
                               7197                 :                : 
  435 dean.a.rasheed@gmail     7198                 :              3 : out_of_range:
                               7199         [ +  - ]:              3 :     ereturn(escontext, false,
                               7200                 :                :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7201                 :                :              errmsg("value overflows numeric format")));
                               7202                 :                : 
                               7203                 :             21 : invalid_syntax:
                               7204         [ +  - ]:             21 :     ereturn(escontext, false,
                               7205                 :                :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               7206                 :                :              errmsg("invalid input syntax for type %s: \"%s\"",
                               7207                 :                :                     "numeric", str)));
                               7208                 :                : }
                               7209                 :                : 
                               7210                 :                : 
                               7211                 :                : /*
                               7212                 :                :  * Return the numeric value of a single hex digit.
                               7213                 :                :  */
                               7214                 :                : static inline int
  447                          7215                 :            354 : xdigit_value(char dig)
                               7216                 :                : {
                               7217   [ +  -  +  + ]:            447 :     return dig >= '0' && dig <= '9' ? dig - '0' :
                               7218   [ +  +  +  - ]:            147 :         dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
                               7219   [ +  -  +  - ]:             54 :         dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
                               7220                 :                : }
                               7221                 :                : 
                               7222                 :                : /*
                               7223                 :                :  * set_var_from_non_decimal_integer_str()
                               7224                 :                :  *
                               7225                 :                :  *  Parse a string containing a non-decimal integer
                               7226                 :                :  *
                               7227                 :                :  * This function does not handle leading or trailing spaces.  It returns
                               7228                 :                :  * the end+1 position parsed into *endptr, so that caller can check for
                               7229                 :                :  * trailing spaces/garbage if deemed necessary.
                               7230                 :                :  *
                               7231                 :                :  * cp is the place to actually start parsing; str is what to use in error
                               7232                 :                :  * reports.  The number's sign and base prefix indicator (e.g., "0x") are
                               7233                 :                :  * assumed to have already been parsed, so cp should point to the number's
                               7234                 :                :  * first digit in the base specified.
                               7235                 :                :  *
                               7236                 :                :  * base is expected to be 2, 8 or 16.
                               7237                 :                :  *
                               7238                 :                :  * Returns true on success, false on failure (if escontext points to an
                               7239                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               7240                 :                :  */
                               7241                 :                : static bool
                               7242                 :             78 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
                               7243                 :                :                                      int base, NumericVar *dest,
                               7244                 :                :                                      const char **endptr, Node *escontext)
                               7245                 :                : {
                               7246                 :             78 :     const char *firstdigit = cp;
                               7247                 :                :     int64       tmp;
                               7248                 :                :     int64       mul;
                               7249                 :                :     NumericVar  tmp_var;
                               7250                 :                : 
                               7251                 :             78 :     init_var(&tmp_var);
                               7252                 :                : 
                               7253                 :             78 :     zero_var(dest);
                               7254                 :                : 
                               7255                 :                :     /*
                               7256                 :                :      * Process input digits in groups that fit in int64.  Here "tmp" is the
                               7257                 :                :      * value of the digits in the group, and "mul" is base^n, where n is the
                               7258                 :                :      * number of digits in the group.  Thus tmp < mul, and we must start a new
                               7259                 :                :      * group when mul * base threatens to overflow PG_INT64_MAX.
                               7260                 :                :      */
                               7261                 :             78 :     tmp = 0;
                               7262                 :             78 :     mul = 1;
                               7263                 :                : 
                               7264         [ +  + ]:             78 :     if (base == 16)
                               7265                 :                :     {
                               7266         [ +  + ]:            414 :         while (*cp)
                               7267                 :                :         {
                               7268         [ +  + ]:            399 :             if (isxdigit((unsigned char) *cp))
                               7269                 :                :             {
                               7270         [ +  + ]:            354 :                 if (mul > PG_INT64_MAX / 16)
                               7271                 :                :                 {
                               7272                 :                :                     /* Add the contribution from this group of digits */
                               7273                 :             15 :                     int64_to_numericvar(mul, &tmp_var);
                               7274                 :             15 :                     mul_var(dest, &tmp_var, dest, 0);
                               7275                 :             15 :                     int64_to_numericvar(tmp, &tmp_var);
                               7276                 :             15 :                     add_var(dest, &tmp_var, dest);
                               7277                 :                : 
                               7278                 :                :                     /* Result will overflow if weight overflows int16 */
                               7279         [ -  + ]:             15 :                     if (dest->weight > SHRT_MAX)
  447 dean.a.rasheed@gmail     7280                 :UBC           0 :                         goto out_of_range;
                               7281                 :                : 
                               7282                 :                :                     /* Begin a new group */
  447 dean.a.rasheed@gmail     7283                 :CBC          15 :                     tmp = 0;
                               7284                 :             15 :                     mul = 1;
                               7285                 :                :                 }
                               7286                 :                : 
                               7287                 :            354 :                 tmp = tmp * 16 + xdigit_value(*cp++);
                               7288                 :            354 :                 mul = mul * 16;
                               7289                 :                :             }
  435                          7290         [ +  + ]:             45 :             else if (*cp == '_')
                               7291                 :                :             {
                               7292                 :                :                 /* Underscore must be followed by more digits */
                               7293                 :             33 :                 cp++;
                               7294         [ +  + ]:             33 :                 if (!isxdigit((unsigned char) *cp))
                               7295                 :              9 :                     goto invalid_syntax;
                               7296                 :                :             }
                               7297                 :                :             else
  447                          7298                 :             12 :                 break;
                               7299                 :                :         }
                               7300                 :                :     }
                               7301         [ +  + ]:             42 :     else if (base == 8)
                               7302                 :                :     {
                               7303         [ +  + ]:            318 :         while (*cp)
                               7304                 :                :         {
                               7305   [ +  +  +  + ]:            303 :             if (*cp >= '0' && *cp <= '7')
                               7306                 :                :             {
                               7307         [ +  + ]:            279 :                 if (mul > PG_INT64_MAX / 8)
                               7308                 :                :                 {
                               7309                 :                :                     /* Add the contribution from this group of digits */
                               7310                 :              9 :                     int64_to_numericvar(mul, &tmp_var);
                               7311                 :              9 :                     mul_var(dest, &tmp_var, dest, 0);
                               7312                 :              9 :                     int64_to_numericvar(tmp, &tmp_var);
                               7313                 :              9 :                     add_var(dest, &tmp_var, dest);
                               7314                 :                : 
                               7315                 :                :                     /* Result will overflow if weight overflows int16 */
                               7316         [ -  + ]:              9 :                     if (dest->weight > SHRT_MAX)
  447 dean.a.rasheed@gmail     7317                 :UBC           0 :                         goto out_of_range;
                               7318                 :                : 
                               7319                 :                :                     /* Begin a new group */
  447 dean.a.rasheed@gmail     7320                 :CBC           9 :                     tmp = 0;
                               7321                 :              9 :                     mul = 1;
                               7322                 :                :                 }
                               7323                 :                : 
                               7324                 :            279 :                 tmp = tmp * 8 + (*cp++ - '0');
                               7325                 :            279 :                 mul = mul * 8;
                               7326                 :                :             }
  435                          7327         [ +  + ]:             24 :             else if (*cp == '_')
                               7328                 :                :             {
                               7329                 :                :                 /* Underscore must be followed by more digits */
                               7330                 :             18 :                 cp++;
                               7331   [ +  -  -  + ]:             18 :                 if (*cp < '0' || *cp > '7')
  435 dean.a.rasheed@gmail     7332                 :UBC           0 :                     goto invalid_syntax;
                               7333                 :                :             }
                               7334                 :                :             else
  447 dean.a.rasheed@gmail     7335                 :CBC           6 :                 break;
                               7336                 :                :         }
                               7337                 :                :     }
                               7338         [ +  - ]:             21 :     else if (base == 2)
                               7339                 :                :     {
                               7340         [ +  + ]:            780 :         while (*cp)
                               7341                 :                :         {
                               7342   [ +  +  +  + ]:            765 :             if (*cp >= '0' && *cp <= '1')
                               7343                 :                :             {
                               7344         [ +  + ]:            708 :                 if (mul > PG_INT64_MAX / 2)
                               7345                 :                :                 {
                               7346                 :                :                     /* Add the contribution from this group of digits */
                               7347                 :              9 :                     int64_to_numericvar(mul, &tmp_var);
                               7348                 :              9 :                     mul_var(dest, &tmp_var, dest, 0);
                               7349                 :              9 :                     int64_to_numericvar(tmp, &tmp_var);
                               7350                 :              9 :                     add_var(dest, &tmp_var, dest);
                               7351                 :                : 
                               7352                 :                :                     /* Result will overflow if weight overflows int16 */
                               7353         [ -  + ]:              9 :                     if (dest->weight > SHRT_MAX)
  447 dean.a.rasheed@gmail     7354                 :UBC           0 :                         goto out_of_range;
                               7355                 :                : 
                               7356                 :                :                     /* Begin a new group */
  447 dean.a.rasheed@gmail     7357                 :CBC           9 :                     tmp = 0;
                               7358                 :              9 :                     mul = 1;
                               7359                 :                :                 }
                               7360                 :                : 
                               7361                 :            708 :                 tmp = tmp * 2 + (*cp++ - '0');
                               7362                 :            708 :                 mul = mul * 2;
                               7363                 :                :             }
  435                          7364         [ +  + ]:             57 :             else if (*cp == '_')
                               7365                 :                :             {
                               7366                 :                :                 /* Underscore must be followed by more digits */
                               7367                 :             51 :                 cp++;
                               7368   [ +  -  -  + ]:             51 :                 if (*cp < '0' || *cp > '1')
  435 dean.a.rasheed@gmail     7369                 :UBC           0 :                     goto invalid_syntax;
                               7370                 :                :             }
                               7371                 :                :             else
  447 dean.a.rasheed@gmail     7372                 :CBC           6 :                 break;
                               7373                 :                :         }
                               7374                 :                :     }
                               7375                 :                :     else
                               7376                 :                :         /* Should never happen; treat as invalid input */
  447 dean.a.rasheed@gmail     7377                 :UBC           0 :         goto invalid_syntax;
                               7378                 :                : 
                               7379                 :                :     /* Check that we got at least one digit */
  447 dean.a.rasheed@gmail     7380         [ -  + ]:CBC          69 :     if (unlikely(cp == firstdigit))
  447 dean.a.rasheed@gmail     7381                 :UBC           0 :         goto invalid_syntax;
                               7382                 :                : 
                               7383                 :                :     /* Add the contribution from the final group of digits */
  447 dean.a.rasheed@gmail     7384                 :CBC          69 :     int64_to_numericvar(mul, &tmp_var);
                               7385                 :             69 :     mul_var(dest, &tmp_var, dest, 0);
                               7386                 :             69 :     int64_to_numericvar(tmp, &tmp_var);
                               7387                 :             69 :     add_var(dest, &tmp_var, dest);
                               7388                 :                : 
                               7389         [ -  + ]:             69 :     if (dest->weight > SHRT_MAX)
  447 dean.a.rasheed@gmail     7390                 :UBC           0 :         goto out_of_range;
                               7391                 :                : 
  447 dean.a.rasheed@gmail     7392                 :CBC          69 :     dest->sign = sign;
                               7393                 :                : 
                               7394                 :             69 :     free_var(&tmp_var);
                               7395                 :                : 
                               7396                 :                :     /* Return end+1 position for caller */
                               7397                 :             69 :     *endptr = cp;
                               7398                 :                : 
                               7399                 :             69 :     return true;
                               7400                 :                : 
  447 dean.a.rasheed@gmail     7401                 :UBC           0 : out_of_range:
                               7402         [ #  # ]:              0 :     ereturn(escontext, false,
                               7403                 :                :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7404                 :                :              errmsg("value overflows numeric format")));
                               7405                 :                : 
  447 dean.a.rasheed@gmail     7406                 :CBC           9 : invalid_syntax:
                               7407         [ +  - ]:              9 :     ereturn(escontext, false,
                               7408                 :                :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               7409                 :                :              errmsg("invalid input syntax for type %s: \"%s\"",
                               7410                 :                :                     "numeric", str)));
                               7411                 :                : }
                               7412                 :                : 
                               7413                 :                : 
                               7414                 :                : /*
                               7415                 :                :  * set_var_from_num() -
                               7416                 :                :  *
                               7417                 :                :  *  Convert the packed db format into a variable
                               7418                 :                :  */
                               7419                 :                : static void
 9091 bruce@momjian.us         7420                 :           6401 : set_var_from_num(Numeric num, NumericVar *dest)
                               7421                 :                : {
                               7422                 :                :     int         ndigits;
                               7423                 :                : 
 6641                          7424         [ +  + ]:           6401 :     ndigits = NUMERIC_NDIGITS(num);
                               7425                 :                : 
 7695 tgl@sss.pgh.pa.us        7426                 :           6401 :     alloc_var(dest, ndigits);
                               7427                 :                : 
 5003 rhaas@postgresql.org     7428   [ +  +  +  + ]:           6401 :     dest->weight = NUMERIC_WEIGHT(num);
 9091 bruce@momjian.us         7429   [ +  +  -  + ]:           6401 :     dest->sign = NUMERIC_SIGN(num);
 7695 tgl@sss.pgh.pa.us        7430         [ +  + ]:           6401 :     dest->dscale = NUMERIC_DSCALE(num);
                               7431                 :                : 
 5003 rhaas@postgresql.org     7432         [ +  + ]:           6401 :     memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
 9237 JanWieck@Yahoo.com       7433                 :           6401 : }
                               7434                 :                : 
                               7435                 :                : 
                               7436                 :                : /*
                               7437                 :                :  * init_var_from_num() -
                               7438                 :                :  *
                               7439                 :                :  *  Initialize a variable from packed db format. The digits array is not
                               7440                 :                :  *  copied, which saves some cycles when the resulting var is not modified.
                               7441                 :                :  *  Also, there's no need to call free_var(), as long as you don't assign any
                               7442                 :                :  *  other value to it (with set_var_* functions, or by using the var as the
                               7443                 :                :  *  destination of a function like add_var())
                               7444                 :                :  *
                               7445                 :                :  *  CAUTION: Do not modify the digits buffer of a var initialized with this
                               7446                 :                :  *  function, e.g by calling round_var() or trunc_var(), as the changes will
                               7447                 :                :  *  propagate to the original Numeric! It's OK to use it as the destination
                               7448                 :                :  *  argument of one of the calculational functions, though.
                               7449                 :                :  */
                               7450                 :                : static void
 4162 heikki.linnakangas@i     7451                 :        2546823 : init_var_from_num(Numeric num, NumericVar *dest)
                               7452                 :                : {
                               7453         [ +  + ]:        2546823 :     dest->ndigits = NUMERIC_NDIGITS(num);
                               7454   [ +  +  +  + ]:        2546823 :     dest->weight = NUMERIC_WEIGHT(num);
                               7455   [ +  +  -  + ]:        2546823 :     dest->sign = NUMERIC_SIGN(num);
                               7456         [ +  + ]:        2546823 :     dest->dscale = NUMERIC_DSCALE(num);
                               7457         [ +  + ]:        2546823 :     dest->digits = NUMERIC_DIGITS(num);
 3973 bruce@momjian.us         7458                 :        2546823 :     dest->buf = NULL;            /* digits array is not palloc'd */
 4162 heikki.linnakangas@i     7459                 :        2546823 : }
                               7460                 :                : 
                               7461                 :                : 
                               7462                 :                : /*
                               7463                 :                :  * set_var_from_var() -
                               7464                 :                :  *
                               7465                 :                :  *  Copy one variable into another
                               7466                 :                :  */
                               7467                 :                : static void
 2408 andres@anarazel.de       7468                 :          18432 : set_var_from_var(const NumericVar *value, NumericVar *dest)
                               7469                 :                : {
                               7470                 :                :     NumericDigit *newbuf;
                               7471                 :                : 
 8853 tgl@sss.pgh.pa.us        7472                 :          18432 :     newbuf = digitbuf_alloc(value->ndigits + 1);
                               7473                 :          18432 :     newbuf[0] = 0;              /* spare digit for rounding */
 3178                          7474         [ +  + ]:          18432 :     if (value->ndigits > 0)       /* else value->digits might be null */
                               7475                 :          17965 :         memcpy(newbuf + 1, value->digits,
                               7476                 :          17965 :                value->ndigits * sizeof(NumericDigit));
                               7477                 :                : 
 9237 JanWieck@Yahoo.com       7478         [ +  + ]:          18432 :     digitbuf_free(dest->buf);
                               7479                 :                : 
 7375 neilc@samurai.com        7480                 :          18432 :     memmove(dest, value, sizeof(NumericVar));
 9091 bruce@momjian.us         7481                 :          18432 :     dest->buf = newbuf;
 8853 tgl@sss.pgh.pa.us        7482                 :          18432 :     dest->digits = newbuf + 1;
                               7483                 :          18432 : }
                               7484                 :                : 
                               7485                 :                : 
                               7486                 :                : /*
                               7487                 :                :  * get_str_from_var() -
                               7488                 :                :  *
                               7489                 :                :  *  Convert a var to text representation (guts of numeric_out).
                               7490                 :                :  *  The var is displayed to the number of digits indicated by its dscale.
                               7491                 :                :  *  Returns a palloc'd string.
                               7492                 :                :  */
                               7493                 :                : static char *
 2408 andres@anarazel.de       7494                 :         398834 : get_str_from_var(const NumericVar *var)
                               7495                 :                : {
                               7496                 :                :     int         dscale;
                               7497                 :                :     char       *str;
                               7498                 :                :     char       *cp;
                               7499                 :                :     char       *endcp;
                               7500                 :                :     int         i;
                               7501                 :                :     int         d;
                               7502                 :                :     NumericDigit dig;
                               7503                 :                : 
                               7504                 :                : #if DEC_DIGITS > 1
                               7505                 :                :     NumericDigit d1;
                               7506                 :                : #endif
                               7507                 :                : 
 4162 heikki.linnakangas@i     7508                 :         398834 :     dscale = var->dscale;
                               7509                 :                : 
                               7510                 :                :     /*
                               7511                 :                :      * Allocate space for the result.
                               7512                 :                :      *
                               7513                 :                :      * i is set to the # of decimal digits before decimal point. dscale is the
                               7514                 :                :      * # of decimal digits we will print after decimal point. We may generate
                               7515                 :                :      * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
                               7516                 :                :      * need room for sign, decimal point, null terminator.
                               7517                 :                :      */
 7695 tgl@sss.pgh.pa.us        7518                 :         398834 :     i = (var->weight + 1) * DEC_DIGITS;
                               7519         [ +  + ]:         398834 :     if (i <= 0)
                               7520                 :          69576 :         i = 1;
                               7521                 :                : 
                               7522                 :         398834 :     str = palloc(i + dscale + DEC_DIGITS + 2);
 8853                          7523                 :         398834 :     cp = str;
                               7524                 :                : 
                               7525                 :                :     /*
                               7526                 :                :      * Output a dash for negative values
                               7527                 :                :      */
                               7528         [ +  + ]:         398834 :     if (var->sign == NUMERIC_NEG)
                               7529                 :           2473 :         *cp++ = '-';
                               7530                 :                : 
                               7531                 :                :     /*
                               7532                 :                :      * Output all digits before the decimal point
                               7533                 :                :      */
 7695                          7534         [ +  + ]:         398834 :     if (var->weight < 0)
                               7535                 :                :     {
                               7536                 :          69576 :         d = var->weight + 1;
                               7537                 :          69576 :         *cp++ = '0';
                               7538                 :                :     }
                               7539                 :                :     else
                               7540                 :                :     {
                               7541         [ +  + ]:         710965 :         for (d = 0; d <= var->weight; d++)
                               7542                 :                :         {
                               7543         [ +  + ]:         381707 :             dig = (d < var->ndigits) ? var->digits[d] : 0;
                               7544                 :                :             /* In the first digit, suppress extra leading decimal zeroes */
                               7545                 :                : #if DEC_DIGITS == 4
                               7546                 :                :             {
 7559 bruce@momjian.us         7547                 :         381707 :                 bool        putit = (d > 0);
                               7548                 :                : 
 7695 tgl@sss.pgh.pa.us        7549                 :         381707 :                 d1 = dig / 1000;
                               7550                 :         381707 :                 dig -= d1 * 1000;
                               7551                 :         381707 :                 putit |= (d1 > 0);
                               7552         [ +  + ]:         381707 :                 if (putit)
                               7553                 :          55691 :                     *cp++ = d1 + '0';
                               7554                 :         381707 :                 d1 = dig / 100;
                               7555                 :         381707 :                 dig -= d1 * 100;
                               7556                 :         381707 :                 putit |= (d1 > 0);
                               7557         [ +  + ]:         381707 :                 if (putit)
                               7558                 :         258128 :                     *cp++ = d1 + '0';
                               7559                 :         381707 :                 d1 = dig / 10;
                               7560                 :         381707 :                 dig -= d1 * 10;
                               7561                 :         381707 :                 putit |= (d1 > 0);
                               7562         [ +  + ]:         381707 :                 if (putit)
                               7563                 :         321560 :                     *cp++ = d1 + '0';
                               7564                 :         381707 :                 *cp++ = dig + '0';
                               7565                 :                :             }
                               7566                 :                : #elif DEC_DIGITS == 2
                               7567                 :                :             d1 = dig / 10;
                               7568                 :                :             dig -= d1 * 10;
                               7569                 :                :             if (d1 > 0 || d > 0)
                               7570                 :                :                 *cp++ = d1 + '0';
                               7571                 :                :             *cp++ = dig + '0';
                               7572                 :                : #elif DEC_DIGITS == 1
                               7573                 :                :             *cp++ = dig + '0';
                               7574                 :                : #else
                               7575                 :                : #error unsupported NBASE
                               7576                 :                : #endif
                               7577                 :                :         }
                               7578                 :                :     }
                               7579                 :                : 
                               7580                 :                :     /*
                               7581                 :                :      * If requested, output a decimal point and all the digits that follow it.
                               7582                 :                :      * We initially put out a multiple of DEC_DIGITS digits, then truncate if
                               7583                 :                :      * needed.
                               7584                 :                :      */
 8853                          7585         [ +  + ]:         398834 :     if (dscale > 0)
                               7586                 :                :     {
                               7587                 :         321783 :         *cp++ = '.';
 7695                          7588                 :         321783 :         endcp = cp + dscale;
                               7589         [ +  + ]:         949093 :         for (i = 0; i < dscale; d++, i += DEC_DIGITS)
                               7590                 :                :         {
                               7591   [ +  +  +  + ]:         627310 :             dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
                               7592                 :                : #if DEC_DIGITS == 4
                               7593                 :         627310 :             d1 = dig / 1000;
                               7594                 :         627310 :             dig -= d1 * 1000;
                               7595                 :         627310 :             *cp++ = d1 + '0';
                               7596                 :         627310 :             d1 = dig / 100;
                               7597                 :         627310 :             dig -= d1 * 100;
                               7598                 :         627310 :             *cp++ = d1 + '0';
                               7599                 :         627310 :             d1 = dig / 10;
                               7600                 :         627310 :             dig -= d1 * 10;
                               7601                 :         627310 :             *cp++ = d1 + '0';
                               7602                 :         627310 :             *cp++ = dig + '0';
                               7603                 :                : #elif DEC_DIGITS == 2
                               7604                 :                :             d1 = dig / 10;
                               7605                 :                :             dig -= d1 * 10;
                               7606                 :                :             *cp++ = d1 + '0';
                               7607                 :                :             *cp++ = dig + '0';
                               7608                 :                : #elif DEC_DIGITS == 1
                               7609                 :                :             *cp++ = dig + '0';
                               7610                 :                : #else
                               7611                 :                : #error unsupported NBASE
                               7612                 :                : #endif
                               7613                 :                :         }
                               7614                 :         321783 :         cp = endcp;
                               7615                 :                :     }
                               7616                 :                : 
                               7617                 :                :     /*
                               7618                 :                :      * terminate the string and return it
                               7619                 :                :      */
 8853                          7620                 :         398834 :     *cp = '\0';
                               7621                 :         398834 :     return str;
                               7622                 :                : }
                               7623                 :                : 
                               7624                 :                : /*
                               7625                 :                :  * get_str_from_var_sci() -
                               7626                 :                :  *
                               7627                 :                :  *  Convert a var to a normalised scientific notation text representation.
                               7628                 :                :  *  This function does the heavy lifting for numeric_out_sci().
                               7629                 :                :  *
                               7630                 :                :  *  This notation has the general form a * 10^b, where a is known as the
                               7631                 :                :  *  "significand" and b is known as the "exponent".
                               7632                 :                :  *
                               7633                 :                :  *  Because we can't do superscript in ASCII (and because we want to copy
                               7634                 :                :  *  printf's behaviour) we display the exponent using E notation, with a
                               7635                 :                :  *  minimum of two exponent digits.
                               7636                 :                :  *
                               7637                 :                :  *  For example, the value 1234 could be output as 1.2e+03.
                               7638                 :                :  *
                               7639                 :                :  *  We assume that the exponent can fit into an int32.
                               7640                 :                :  *
                               7641                 :                :  *  rscale is the number of decimal digits desired after the decimal point in
                               7642                 :                :  *  the output, negative values will be treated as meaning zero.
                               7643                 :                :  *
                               7644                 :                :  *  Returns a palloc'd string.
                               7645                 :                :  */
                               7646                 :                : static char *
 2408 andres@anarazel.de       7647                 :            108 : get_str_from_var_sci(const NumericVar *var, int rscale)
                               7648                 :                : {
                               7649                 :                :     int32       exponent;
                               7650                 :                :     NumericVar  tmp_var;
                               7651                 :                :     size_t      len;
                               7652                 :                :     char       *str;
                               7653                 :                :     char       *sig_out;
                               7654                 :                : 
 5361 tgl@sss.pgh.pa.us        7655         [ -  + ]:            108 :     if (rscale < 0)
 5361 tgl@sss.pgh.pa.us        7656                 :UBC           0 :         rscale = 0;
                               7657                 :                : 
                               7658                 :                :     /*
                               7659                 :                :      * Determine the exponent of this number in normalised form.
                               7660                 :                :      *
                               7661                 :                :      * This is the exponent required to represent the number with only one
                               7662                 :                :      * significant digit before the decimal place.
                               7663                 :                :      */
 5361 tgl@sss.pgh.pa.us        7664         [ +  + ]:CBC         108 :     if (var->ndigits > 0)
                               7665                 :                :     {
                               7666                 :             99 :         exponent = (var->weight + 1) * DEC_DIGITS;
                               7667                 :                : 
                               7668                 :                :         /*
                               7669                 :                :          * Compensate for leading decimal zeroes in the first numeric digit by
                               7670                 :                :          * decrementing the exponent.
                               7671                 :                :          */
                               7672                 :             99 :         exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
                               7673                 :                :     }
                               7674                 :                :     else
                               7675                 :                :     {
                               7676                 :                :         /*
                               7677                 :                :          * If var has no digits, then it must be zero.
                               7678                 :                :          *
                               7679                 :                :          * Zero doesn't technically have a meaningful exponent in normalised
                               7680                 :                :          * notation, but we just display the exponent as zero for consistency
                               7681                 :                :          * of output.
                               7682                 :                :          */
                               7683                 :              9 :         exponent = 0;
                               7684                 :                :     }
                               7685                 :                : 
                               7686                 :                :     /*
                               7687                 :                :      * Divide var by 10^exponent to get the significand, rounding to rscale
                               7688                 :                :      * decimal digits in the process.
                               7689                 :                :      */
  983 dean.a.rasheed@gmail     7690                 :            108 :     init_var(&tmp_var);
                               7691                 :                : 
                               7692                 :            108 :     power_ten_int(exponent, &tmp_var);
                               7693                 :            108 :     div_var(var, &tmp_var, &tmp_var, rscale, true);
                               7694                 :            108 :     sig_out = get_str_from_var(&tmp_var);
                               7695                 :                : 
                               7696                 :            108 :     free_var(&tmp_var);
                               7697                 :                : 
                               7698                 :                :     /*
                               7699                 :                :      * Allocate space for the result.
                               7700                 :                :      *
                               7701                 :                :      * In addition to the significand, we need room for the exponent
                               7702                 :                :      * decoration ("e"), the sign of the exponent, up to 10 digits for the
                               7703                 :                :      * exponent itself, and of course the null terminator.
                               7704                 :                :      */
 5361 tgl@sss.pgh.pa.us        7705                 :            108 :     len = strlen(sig_out) + 13;
                               7706                 :            108 :     str = palloc(len);
                               7707                 :            108 :     snprintf(str, len, "%se%+03d", sig_out, exponent);
                               7708                 :                : 
                               7709                 :            108 :     pfree(sig_out);
                               7710                 :                : 
                               7711                 :            108 :     return str;
                               7712                 :                : }
                               7713                 :                : 
                               7714                 :                : 
                               7715                 :                : /*
                               7716                 :                :  * numericvar_serialize - serialize NumericVar to binary format
                               7717                 :                :  *
                               7718                 :                :  * At variable level, no checks are performed on the weight or dscale, allowing
                               7719                 :                :  * us to pass around intermediate values with higher precision than supported
                               7720                 :                :  * by the numeric type.  Note: this is incompatible with numeric_send/recv(),
                               7721                 :                :  * which use 16-bit integers for these fields.
                               7722                 :                :  */
                               7723                 :                : static void
 1014 dean.a.rasheed@gmail     7724                 :             99 : numericvar_serialize(StringInfo buf, const NumericVar *var)
                               7725                 :                : {
                               7726                 :                :     int         i;
                               7727                 :                : 
                               7728                 :             99 :     pq_sendint32(buf, var->ndigits);
                               7729                 :             99 :     pq_sendint32(buf, var->weight);
                               7730                 :             99 :     pq_sendint32(buf, var->sign);
                               7731                 :             99 :     pq_sendint32(buf, var->dscale);
                               7732         [ +  + ]:         319044 :     for (i = 0; i < var->ndigits; i++)
                               7733                 :         318945 :         pq_sendint16(buf, var->digits[i]);
                               7734                 :             99 : }
                               7735                 :                : 
                               7736                 :                : /*
                               7737                 :                :  * numericvar_deserialize - deserialize binary format to NumericVar
                               7738                 :                :  */
                               7739                 :                : static void
                               7740                 :             99 : numericvar_deserialize(StringInfo buf, NumericVar *var)
                               7741                 :                : {
                               7742                 :                :     int         len,
                               7743                 :                :                 i;
                               7744                 :                : 
                               7745                 :             99 :     len = pq_getmsgint(buf, sizeof(int32));
                               7746                 :                : 
                               7747                 :             99 :     alloc_var(var, len);        /* sets var->ndigits */
                               7748                 :                : 
                               7749                 :             99 :     var->weight = pq_getmsgint(buf, sizeof(int32));
                               7750                 :             99 :     var->sign = pq_getmsgint(buf, sizeof(int32));
                               7751                 :             99 :     var->dscale = pq_getmsgint(buf, sizeof(int32));
                               7752         [ +  + ]:         319044 :     for (i = 0; i < len; i++)
                               7753                 :         318945 :         var->digits[i] = pq_getmsgint(buf, sizeof(int16));
                               7754                 :             99 : }
                               7755                 :                : 
                               7756                 :                : 
                               7757                 :                : /*
                               7758                 :                :  * duplicate_numeric() - copy a packed-format Numeric
                               7759                 :                :  *
                               7760                 :                :  * This will handle NaN and Infinity cases.
                               7761                 :                :  */
                               7762                 :                : static Numeric
 1362 tgl@sss.pgh.pa.us        7763                 :          14246 : duplicate_numeric(Numeric num)
                               7764                 :                : {
                               7765                 :                :     Numeric     res;
                               7766                 :                : 
                               7767                 :          14246 :     res = (Numeric) palloc(VARSIZE(num));
                               7768                 :          14246 :     memcpy(res, num, VARSIZE(num));
                               7769                 :          14246 :     return res;
                               7770                 :                : }
                               7771                 :                : 
                               7772                 :                : /*
                               7773                 :                :  * make_result_opt_error() -
                               7774                 :                :  *
                               7775                 :                :  *  Create the packed db numeric format in palloc()'d memory from
                               7776                 :                :  *  a variable.  This will handle NaN and Infinity cases.
                               7777                 :                :  *
                               7778                 :                :  *  If "have_error" isn't NULL, on overflow *have_error is set to true and
                               7779                 :                :  *  NULL is returned.  This is helpful when caller needs to handle errors.
                               7780                 :                :  */
                               7781                 :                : static Numeric
 1856 akorotkov@postgresql     7782                 :        1636739 : make_result_opt_error(const NumericVar *var, bool *have_error)
                               7783                 :                : {
                               7784                 :                :     Numeric     result;
 7695 tgl@sss.pgh.pa.us        7785                 :        1636739 :     NumericDigit *digits = var->digits;
 9091 bruce@momjian.us         7786                 :        1636739 :     int         weight = var->weight;
                               7787                 :        1636739 :     int         sign = var->sign;
                               7788                 :                :     int         n;
                               7789                 :                :     Size        len;
                               7790                 :                : 
 1714 michael@paquier.xyz      7791         [ +  + ]:        1636739 :     if (have_error)
                               7792                 :          52592 :         *have_error = false;
                               7793                 :                : 
 1362 tgl@sss.pgh.pa.us        7794         [ +  + ]:        1636739 :     if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
                               7795                 :                :     {
                               7796                 :                :         /*
                               7797                 :                :          * Verify valid special value.  This could be just an Assert, perhaps,
                               7798                 :                :          * but it seems worthwhile to expend a few cycles to ensure that we
                               7799                 :                :          * never write any nonzero reserved bits to disk.
                               7800                 :                :          */
                               7801   [ +  +  +  +  :           2553 :         if (!(sign == NUMERIC_NAN ||
                                              -  + ]
                               7802                 :                :               sign == NUMERIC_PINF ||
                               7803                 :                :               sign == NUMERIC_NINF))
 1362 tgl@sss.pgh.pa.us        7804         [ #  # ]:UBC           0 :             elog(ERROR, "invalid numeric sign value 0x%x", sign);
                               7805                 :                : 
 5003 rhaas@postgresql.org     7806                 :CBC        2553 :         result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
                               7807                 :                : 
                               7808                 :           2553 :         SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
 1362 tgl@sss.pgh.pa.us        7809                 :           2553 :         result->choice.n_header = sign;
                               7810                 :                :         /* the header word is all we need */
                               7811                 :                : 
                               7812                 :                :         dump_numeric("make_result()", result);
 9237 JanWieck@Yahoo.com       7813                 :           2553 :         return result;
                               7814                 :                :     }
                               7815                 :                : 
 7695 tgl@sss.pgh.pa.us        7816                 :        1634186 :     n = var->ndigits;
                               7817                 :                : 
                               7818                 :                :     /* truncate leading zeroes */
                               7819   [ +  +  +  + ]:        1634198 :     while (n > 0 && *digits == 0)
                               7820                 :                :     {
                               7821                 :             12 :         digits++;
 9237 JanWieck@Yahoo.com       7822                 :             12 :         weight--;
                               7823                 :             12 :         n--;
                               7824                 :                :     }
                               7825                 :                :     /* truncate trailing zeroes */
 7695 tgl@sss.pgh.pa.us        7826   [ +  +  +  + ]:        1676767 :     while (n > 0 && digits[n - 1] == 0)
 9237 JanWieck@Yahoo.com       7827                 :          42581 :         n--;
                               7828                 :                : 
                               7829                 :                :     /* If zero result, force to weight=0 and positive sign */
                               7830         [ +  + ]:        1634186 :     if (n == 0)
                               7831                 :                :     {
                               7832                 :          47459 :         weight = 0;
 9091 bruce@momjian.us         7833                 :          47459 :         sign = NUMERIC_POS;
                               7834                 :                :     }
                               7835                 :                : 
                               7836                 :                :     /* Build the result */
 5003 rhaas@postgresql.org     7837   [ +  +  +  +  :        1634186 :     if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
                                              +  - ]
                               7838                 :                :     {
                               7839                 :        1633301 :         len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
                               7840                 :        1633301 :         result = (Numeric) palloc(len);
                               7841                 :        1633301 :         SET_VARSIZE(result, len);
 4891 peter_e@gmx.net          7842                 :        1633301 :         result->choice.n_short.n_header =
                               7843                 :                :             (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
                               7844                 :                :              : NUMERIC_SHORT)
 5003 rhaas@postgresql.org     7845         [ +  + ]:        1633301 :             | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
                               7846                 :        1633301 :             | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
                               7847                 :        1633301 :             | (weight & NUMERIC_SHORT_WEIGHT_MASK);
                               7848                 :                :     }
                               7849                 :                :     else
                               7850                 :                :     {
                               7851                 :            885 :         len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
                               7852                 :            885 :         result = (Numeric) palloc(len);
                               7853                 :            885 :         SET_VARSIZE(result, len);
                               7854                 :            885 :         result->choice.n_long.n_sign_dscale =
                               7855                 :            885 :             sign | (var->dscale & NUMERIC_DSCALE_MASK);
                               7856                 :            885 :         result->choice.n_long.n_weight = weight;
                               7857                 :                :     }
                               7858                 :                : 
                               7859   [ +  +  -  + ]:        1634186 :     Assert(NUMERIC_NDIGITS(result) == n);
 3178 tgl@sss.pgh.pa.us        7860         [ +  + ]:        1634186 :     if (n > 0)
                               7861         [ +  + ]:        1586727 :         memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
                               7862                 :                : 
                               7863                 :                :     /* Check for overflow of int16 fields */
 5003 rhaas@postgresql.org     7864   [ +  +  +  +  :        1634186 :     if (NUMERIC_WEIGHT(result) != weight ||
                                              +  + ]
 7695 tgl@sss.pgh.pa.us        7865   [ +  +  -  + ]:        1634174 :         NUMERIC_DSCALE(result) != var->dscale)
                               7866                 :                :     {
 1856 akorotkov@postgresql     7867         [ +  + ]:             12 :         if (have_error)
                               7868                 :                :         {
                               7869                 :              9 :             *have_error = true;
                               7870                 :              9 :             return NULL;
                               7871                 :                :         }
                               7872                 :                :         else
                               7873                 :                :         {
                               7874         [ +  - ]:              3 :             ereport(ERROR,
                               7875                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7876                 :                :                      errmsg("value overflows numeric format")));
                               7877                 :                :         }
                               7878                 :                :     }
                               7879                 :                : 
                               7880                 :                :     dump_numeric("make_result()", result);
 9237 JanWieck@Yahoo.com       7881                 :        1634174 :     return result;
                               7882                 :                : }
                               7883                 :                : 
                               7884                 :                : 
                               7885                 :                : /*
                               7886                 :                :  * make_result() -
                               7887                 :                :  *
                               7888                 :                :  *  An interface to make_result_opt_error() without "have_error" argument.
                               7889                 :                :  */
                               7890                 :                : static Numeric
 1856 akorotkov@postgresql     7891                 :        1064849 : make_result(const NumericVar *var)
                               7892                 :                : {
                               7893                 :        1064849 :     return make_result_opt_error(var, NULL);
                               7894                 :                : }
                               7895                 :                : 
                               7896                 :                : 
                               7897                 :                : /*
                               7898                 :                :  * apply_typmod() -
                               7899                 :                :  *
                               7900                 :                :  *  Do bounds checking and rounding according to the specified typmod.
                               7901                 :                :  *  Note that this is only applied to normal finite values.
                               7902                 :                :  *
                               7903                 :                :  * Returns true on success, false on failure (if escontext points to an
                               7904                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               7905                 :                :  */
                               7906                 :                : static bool
  492 tgl@sss.pgh.pa.us        7907                 :          54662 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
                               7908                 :                : {
                               7909                 :                :     int         precision;
                               7910                 :                :     int         scale;
                               7911                 :                :     int         maxdigits;
                               7912                 :                :     int         ddigits;
                               7913                 :                :     int         i;
                               7914                 :                : 
                               7915                 :                :     /* Do nothing if we have an invalid typmod */
  993 dean.a.rasheed@gmail     7916         [ +  + ]:          54662 :     if (!is_valid_numeric_typmod(typmod))
  492 tgl@sss.pgh.pa.us        7917                 :          52328 :         return true;
                               7918                 :                : 
  993 dean.a.rasheed@gmail     7919                 :           2334 :     precision = numeric_typmod_precision(typmod);
                               7920                 :           2334 :     scale = numeric_typmod_scale(typmod);
 7695 tgl@sss.pgh.pa.us        7921                 :           2334 :     maxdigits = precision - scale;
                               7922                 :                : 
                               7923                 :                :     /* Round to target scale (and set var->dscale) */
                               7924                 :           2334 :     round_var(var, scale);
                               7925                 :                : 
                               7926                 :                :     /* but don't allow var->dscale to be negative */
  993 dean.a.rasheed@gmail     7927         [ +  + ]:           2334 :     if (var->dscale < 0)
                               7928                 :             63 :         var->dscale = 0;
                               7929                 :                : 
                               7930                 :                :     /*
                               7931                 :                :      * Check for overflow - note we can't do this before rounding, because
                               7932                 :                :      * rounding could raise the weight.  Also note that the var's weight could
                               7933                 :                :      * be inflated by leading zeroes, which will be stripped before storage
                               7934                 :                :      * but perhaps might not have been yet. In any case, we must recognize a
                               7935                 :                :      * true zero, whose weight doesn't mean anything.
                               7936                 :                :      */
 7695 tgl@sss.pgh.pa.us        7937                 :           2334 :     ddigits = (var->weight + 1) * DEC_DIGITS;
                               7938         [ +  + ]:           2334 :     if (ddigits > maxdigits)
                               7939                 :                :     {
                               7940                 :                :         /* Determine true weight; and check for all-zero result */
 8856                          7941         [ +  + ]:            191 :         for (i = 0; i < var->ndigits; i++)
                               7942                 :                :         {
 7695                          7943                 :            184 :             NumericDigit dig = var->digits[i];
                               7944                 :                : 
                               7945         [ +  - ]:            184 :             if (dig)
                               7946                 :                :             {
                               7947                 :                :                 /* Adjust for any high-order decimal zero digits */
                               7948                 :                : #if DEC_DIGITS == 4
                               7949         [ +  + ]:            184 :                 if (dig < 10)
                               7950                 :            117 :                     ddigits -= 3;
                               7951         [ +  + ]:             67 :                 else if (dig < 100)
                               7952                 :             33 :                     ddigits -= 2;
                               7953         [ +  + ]:             34 :                 else if (dig < 1000)
                               7954                 :             25 :                     ddigits -= 1;
                               7955                 :                : #elif DEC_DIGITS == 2
                               7956                 :                :                 if (dig < 10)
                               7957                 :                :                     ddigits -= 1;
                               7958                 :                : #elif DEC_DIGITS == 1
                               7959                 :                :                 /* no adjustment */
                               7960                 :                : #else
                               7961                 :                : #error unsupported NBASE
                               7962                 :                : #endif
                               7963         [ +  + ]:            184 :                 if (ddigits > maxdigits)
  492                          7964   [ +  +  +  +  :             42 :                     ereturn(escontext, false,
                                              +  + ]
                               7965                 :                :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7966                 :                :                              errmsg("numeric field overflow"),
                               7967                 :                :                              errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
                               7968                 :                :                                        precision, scale,
                               7969                 :                :                     /* Display 10^0 as 1 */
                               7970                 :                :                                        maxdigits ? "10^" : "",
                               7971                 :                :                                        maxdigits ? maxdigits : 1
                               7972                 :                :                                        )));
 8856                          7973                 :            142 :                 break;
                               7974                 :                :             }
 7695 tgl@sss.pgh.pa.us        7975                 :UBC           0 :             ddigits -= DEC_DIGITS;
                               7976                 :                :         }
                               7977                 :                :     }
                               7978                 :                : 
  492 tgl@sss.pgh.pa.us        7979                 :CBC        2292 :     return true;
                               7980                 :                : }
                               7981                 :                : 
                               7982                 :                : /*
                               7983                 :                :  * apply_typmod_special() -
                               7984                 :                :  *
                               7985                 :                :  *  Do bounds checking according to the specified typmod, for an Inf or NaN.
                               7986                 :                :  *  For convenience of most callers, the value is presented in packed form.
                               7987                 :                :  *
                               7988                 :                :  * Returns true on success, false on failure (if escontext points to an
                               7989                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               7990                 :                :  */
                               7991                 :                : static bool
                               7992                 :            886 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
                               7993                 :                : {
                               7994                 :                :     int         precision;
                               7995                 :                :     int         scale;
                               7996                 :                : 
 1362                          7997         [ -  + ]:            886 :     Assert(NUMERIC_IS_SPECIAL(num));    /* caller error if not */
                               7998                 :                : 
                               7999                 :                :     /*
                               8000                 :                :      * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
                               8001                 :                :      * but it's a longstanding behavior.  Inf is rejected if we have any
                               8002                 :                :      * typmod restriction, since an infinity shouldn't be claimed to fit in
                               8003                 :                :      * any finite number of digits.
                               8004                 :                :      */
                               8005         [ +  + ]:            886 :     if (NUMERIC_IS_NAN(num))
  492                          8006                 :            385 :         return true;
                               8007                 :                : 
                               8008                 :                :     /* Do nothing if we have a default typmod (-1) */
  993 dean.a.rasheed@gmail     8009         [ +  + ]:            501 :     if (!is_valid_numeric_typmod(typmod))
  492 tgl@sss.pgh.pa.us        8010                 :            492 :         return true;
                               8011                 :                : 
  993 dean.a.rasheed@gmail     8012                 :              9 :     precision = numeric_typmod_precision(typmod);
                               8013                 :              9 :     scale = numeric_typmod_scale(typmod);
                               8014                 :                : 
  492 tgl@sss.pgh.pa.us        8015         [ +  - ]:              9 :     ereturn(escontext, false,
                               8016                 :                :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               8017                 :                :              errmsg("numeric field overflow"),
                               8018                 :                :              errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
                               8019                 :                :                        precision, scale)));
                               8020                 :                : }
                               8021                 :                : 
                               8022                 :                : 
                               8023                 :                : /*
                               8024                 :                :  * Convert numeric to int8, rounding if needed.
                               8025                 :                :  *
                               8026                 :                :  * If overflow, return false (no error is raised).  Return true if okay.
                               8027                 :                :  */
                               8028                 :                : static bool
 2408 andres@anarazel.de       8029                 :           5499 : numericvar_to_int64(const NumericVar *var, int64 *result)
                               8030                 :                : {
                               8031                 :                :     NumericDigit *digits;
                               8032                 :                :     int         ndigits;
                               8033                 :                :     int         weight;
                               8034                 :                :     int         i;
                               8035                 :                :     int64       val;
                               8036                 :                :     bool        neg;
                               8037                 :                :     NumericVar  rounded;
                               8038                 :                : 
                               8039                 :                :     /* Round to nearest integer */
 4162 heikki.linnakangas@i     8040                 :           5499 :     init_var(&rounded);
                               8041                 :           5499 :     set_var_from_var(var, &rounded);
                               8042                 :           5499 :     round_var(&rounded, 0);
                               8043                 :                : 
                               8044                 :                :     /* Check for zero input */
                               8045                 :           5499 :     strip_var(&rounded);
                               8046                 :           5499 :     ndigits = rounded.ndigits;
 7695 tgl@sss.pgh.pa.us        8047         [ +  + ]:           5499 :     if (ndigits == 0)
                               8048                 :                :     {
                               8049                 :            233 :         *result = 0;
 4162 heikki.linnakangas@i     8050                 :            233 :         free_var(&rounded);
 7695 tgl@sss.pgh.pa.us        8051                 :            233 :         return true;
                               8052                 :                :     }
                               8053                 :                : 
                               8054                 :                :     /*
                               8055                 :                :      * For input like 10000000000, we must treat stripped digits as real. So
                               8056                 :                :      * the loop assumes there are weight+1 digits before the decimal point.
                               8057                 :                :      */
 4162 heikki.linnakangas@i     8058                 :           5266 :     weight = rounded.weight;
 7559 bruce@momjian.us         8059   [ +  -  -  + ]:           5266 :     Assert(weight >= 0 && ndigits <= weight + 1);
                               8060                 :                : 
                               8061                 :                :     /*
                               8062                 :                :      * Construct the result. To avoid issues with converting a value
                               8063                 :                :      * corresponding to INT64_MIN (which can't be represented as a positive 64
                               8064                 :                :      * bit two's complement integer), accumulate value as a negative number.
                               8065                 :                :      */
 4162 heikki.linnakangas@i     8066                 :           5266 :     digits = rounded.digits;
                               8067                 :           5266 :     neg = (rounded.sign == NUMERIC_NEG);
 2315 andres@anarazel.de       8068                 :           5266 :     val = -digits[0];
 7591 tgl@sss.pgh.pa.us        8069         [ +  + ]:           7711 :     for (i = 1; i <= weight; i++)
                               8070                 :                :     {
 2315 andres@anarazel.de       8071         [ +  + ]:           2469 :         if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
                               8072                 :                :         {
                               8073                 :             15 :             free_var(&rounded);
                               8074                 :             15 :             return false;
                               8075                 :                :         }
                               8076                 :                : 
                               8077         [ +  + ]:           2454 :         if (i < ndigits)
                               8078                 :                :         {
                               8079         [ +  + ]:           2323 :             if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
                               8080                 :                :             {
 4162 heikki.linnakangas@i     8081                 :              9 :                 free_var(&rounded);
 7695 tgl@sss.pgh.pa.us        8082                 :              9 :                 return false;
                               8083                 :                :             }
                               8084                 :                :         }
                               8085                 :                :     }
                               8086                 :                : 
 4162 heikki.linnakangas@i     8087                 :           5242 :     free_var(&rounded);
                               8088                 :                : 
 2315 andres@anarazel.de       8089         [ +  + ]:           5242 :     if (!neg)
                               8090                 :                :     {
                               8091         [ +  + ]:           4858 :         if (unlikely(val == PG_INT64_MIN))
                               8092                 :             12 :             return false;
                               8093                 :           4846 :         val = -val;
                               8094                 :                :     }
                               8095                 :           5230 :     *result = val;
                               8096                 :                : 
 7695 tgl@sss.pgh.pa.us        8097                 :           5230 :     return true;
                               8098                 :                : }
                               8099                 :                : 
                               8100                 :                : /*
                               8101                 :                :  * Convert int8 value to numeric.
                               8102                 :                :  */
                               8103                 :                : static void
 3313 andres@anarazel.de       8104                 :         940581 : int64_to_numericvar(int64 val, NumericVar *var)
                               8105                 :                : {
                               8106                 :                :     uint64      uval,
                               8107                 :                :                 newuval;
                               8108                 :                :     NumericDigit *ptr;
                               8109                 :                :     int         ndigits;
                               8110                 :                : 
                               8111                 :                :     /* int64 can require at most 19 decimal digits; add one for safety */
 7559 bruce@momjian.us         8112                 :         940581 :     alloc_var(var, 20 / DEC_DIGITS);
 7695 tgl@sss.pgh.pa.us        8113         [ +  + ]:         940581 :     if (val < 0)
                               8114                 :                :     {
                               8115                 :            805 :         var->sign = NUMERIC_NEG;
                               8116                 :            805 :         uval = -val;
                               8117                 :                :     }
                               8118                 :                :     else
                               8119                 :                :     {
                               8120                 :         939776 :         var->sign = NUMERIC_POS;
                               8121                 :         939776 :         uval = val;
                               8122                 :                :     }
                               8123                 :         940581 :     var->dscale = 0;
                               8124         [ +  + ]:         940581 :     if (val == 0)
                               8125                 :                :     {
                               8126                 :          17440 :         var->ndigits = 0;
                               8127                 :          17440 :         var->weight = 0;
                               8128                 :          17440 :         return;
                               8129                 :                :     }
                               8130                 :         923141 :     ptr = var->digits + var->ndigits;
                               8131                 :         923141 :     ndigits = 0;
                               8132                 :                :     do
                               8133                 :                :     {
                               8134                 :        1085673 :         ptr--;
                               8135                 :        1085673 :         ndigits++;
                               8136                 :        1085673 :         newuval = uval / NBASE;
                               8137                 :        1085673 :         *ptr = uval - newuval * NBASE;
                               8138                 :        1085673 :         uval = newuval;
                               8139         [ +  + ]:        1085673 :     } while (uval);
                               8140                 :         923141 :     var->digits = ptr;
                               8141                 :         923141 :     var->ndigits = ndigits;
                               8142                 :         923141 :     var->weight = ndigits - 1;
                               8143                 :                : }
                               8144                 :                : 
                               8145                 :                : /*
                               8146                 :                :  * Convert numeric to uint64, rounding if needed.
                               8147                 :                :  *
                               8148                 :                :  * If overflow, return false (no error is raised).  Return true if okay.
                               8149                 :                :  */
                               8150                 :                : static bool
 1384 fujii@postgresql.org     8151                 :             57 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
                               8152                 :                : {
                               8153                 :                :     NumericDigit *digits;
                               8154                 :                :     int         ndigits;
                               8155                 :                :     int         weight;
                               8156                 :                :     int         i;
                               8157                 :                :     uint64      val;
                               8158                 :                :     NumericVar  rounded;
                               8159                 :                : 
                               8160                 :                :     /* Round to nearest integer */
                               8161                 :             57 :     init_var(&rounded);
                               8162                 :             57 :     set_var_from_var(var, &rounded);
                               8163                 :             57 :     round_var(&rounded, 0);
                               8164                 :                : 
                               8165                 :                :     /* Check for zero input */
                               8166                 :             57 :     strip_var(&rounded);
                               8167                 :             57 :     ndigits = rounded.ndigits;
                               8168         [ +  + ]:             57 :     if (ndigits == 0)
                               8169                 :                :     {
                               8170                 :              9 :         *result = 0;
                               8171                 :              9 :         free_var(&rounded);
                               8172                 :              9 :         return true;
                               8173                 :                :     }
                               8174                 :                : 
                               8175                 :                :     /* Check for negative input */
                               8176         [ +  + ]:             48 :     if (rounded.sign == NUMERIC_NEG)
                               8177                 :                :     {
                               8178                 :              6 :         free_var(&rounded);
                               8179                 :              6 :         return false;
                               8180                 :                :     }
                               8181                 :                : 
                               8182                 :                :     /*
                               8183                 :                :      * For input like 10000000000, we must treat stripped digits as real. So
                               8184                 :                :      * the loop assumes there are weight+1 digits before the decimal point.
                               8185                 :                :      */
                               8186                 :             42 :     weight = rounded.weight;
                               8187   [ +  -  -  + ]:             42 :     Assert(weight >= 0 && ndigits <= weight + 1);
                               8188                 :                : 
                               8189                 :                :     /* Construct the result */
                               8190                 :             42 :     digits = rounded.digits;
                               8191                 :             42 :     val = digits[0];
                               8192         [ +  + ]:            123 :     for (i = 1; i <= weight; i++)
                               8193                 :                :     {
                               8194         [ -  + ]:             87 :         if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
                               8195                 :                :         {
 1384 fujii@postgresql.org     8196                 :UBC           0 :             free_var(&rounded);
                               8197                 :              0 :             return false;
                               8198                 :                :         }
                               8199                 :                : 
 1384 fujii@postgresql.org     8200         [ +  - ]:CBC          87 :         if (i < ndigits)
                               8201                 :                :         {
                               8202         [ +  + ]:             87 :             if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
                               8203                 :                :             {
                               8204                 :              6 :                 free_var(&rounded);
                               8205                 :              6 :                 return false;
                               8206                 :                :             }
                               8207                 :                :         }
                               8208                 :                :     }
                               8209                 :                : 
                               8210                 :             36 :     free_var(&rounded);
                               8211                 :                : 
                               8212                 :             36 :     *result = val;
                               8213                 :                : 
                               8214                 :             36 :     return true;
                               8215                 :                : }
                               8216                 :                : 
                               8217                 :                : #ifdef HAVE_INT128
                               8218                 :                : /*
                               8219                 :                :  * Convert numeric to int128, rounding if needed.
                               8220                 :                :  *
                               8221                 :                :  * If overflow, return false (no error is raised).  Return true if okay.
                               8222                 :                :  */
                               8223                 :                : static bool
 2408 andres@anarazel.de       8224                 :             51 : numericvar_to_int128(const NumericVar *var, int128 *result)
                               8225                 :                : {
                               8226                 :                :     NumericDigit *digits;
                               8227                 :                :     int         ndigits;
                               8228                 :                :     int         weight;
                               8229                 :                :     int         i;
                               8230                 :                :     int128      val,
                               8231                 :                :                 oldval;
                               8232                 :                :     bool        neg;
                               8233                 :                :     NumericVar  rounded;
                               8234                 :                : 
                               8235                 :                :     /* Round to nearest integer */
 2931 rhaas@postgresql.org     8236                 :             51 :     init_var(&rounded);
                               8237                 :             51 :     set_var_from_var(var, &rounded);
                               8238                 :             51 :     round_var(&rounded, 0);
                               8239                 :                : 
                               8240                 :                :     /* Check for zero input */
                               8241                 :             51 :     strip_var(&rounded);
                               8242                 :             51 :     ndigits = rounded.ndigits;
                               8243         [ -  + ]:             51 :     if (ndigits == 0)
                               8244                 :                :     {
 2931 rhaas@postgresql.org     8245                 :UBC           0 :         *result = 0;
                               8246                 :              0 :         free_var(&rounded);
                               8247                 :              0 :         return true;
                               8248                 :                :     }
                               8249                 :                : 
                               8250                 :                :     /*
                               8251                 :                :      * For input like 10000000000, we must treat stripped digits as real. So
                               8252                 :                :      * the loop assumes there are weight+1 digits before the decimal point.
                               8253                 :                :      */
 2931 rhaas@postgresql.org     8254                 :CBC          51 :     weight = rounded.weight;
                               8255   [ +  -  -  + ]:             51 :     Assert(weight >= 0 && ndigits <= weight + 1);
                               8256                 :                : 
                               8257                 :                :     /* Construct the result */
                               8258                 :             51 :     digits = rounded.digits;
                               8259                 :             51 :     neg = (rounded.sign == NUMERIC_NEG);
                               8260                 :             51 :     val = digits[0];
                               8261         [ +  + ]:            114 :     for (i = 1; i <= weight; i++)
                               8262                 :                :     {
                               8263                 :             63 :         oldval = val;
                               8264                 :             63 :         val *= NBASE;
                               8265         [ +  - ]:             63 :         if (i < ndigits)
                               8266                 :             63 :             val += digits[i];
                               8267                 :                : 
                               8268                 :                :         /*
                               8269                 :                :          * The overflow check is a bit tricky because we want to accept
                               8270                 :                :          * INT128_MIN, which will overflow the positive accumulator.  We can
                               8271                 :                :          * detect this case easily though because INT128_MIN is the only
                               8272                 :                :          * nonzero value for which -val == val (on a two's complement machine,
                               8273                 :                :          * anyway).
                               8274                 :                :          */
                               8275         [ -  + ]:             63 :         if ((val / NBASE) != oldval)    /* possible overflow? */
                               8276                 :                :         {
 2931 rhaas@postgresql.org     8277   [ #  #  #  #  :UBC           0 :             if (!neg || (-val) != val || val == 0 || oldval < 0)
                                        #  #  #  # ]
                               8278                 :                :             {
                               8279                 :              0 :                 free_var(&rounded);
                               8280                 :              0 :                 return false;
                               8281                 :                :             }
                               8282                 :                :         }
                               8283                 :                :     }
                               8284                 :                : 
 2931 rhaas@postgresql.org     8285                 :CBC          51 :     free_var(&rounded);
                               8286                 :                : 
                               8287         [ -  + ]:             51 :     *result = neg ? -val : val;
                               8288                 :             51 :     return true;
                               8289                 :                : }
                               8290                 :                : 
                               8291                 :                : /*
                               8292                 :                :  * Convert 128 bit integer to numeric.
                               8293                 :                :  */
                               8294                 :                : static void
 3313 andres@anarazel.de       8295                 :           4312 : int128_to_numericvar(int128 val, NumericVar *var)
                               8296                 :                : {
                               8297                 :                :     uint128     uval,
                               8298                 :                :                 newuval;
                               8299                 :                :     NumericDigit *ptr;
                               8300                 :                :     int         ndigits;
                               8301                 :                : 
                               8302                 :                :     /* int128 can require at most 39 decimal digits; add one for safety */
                               8303                 :           4312 :     alloc_var(var, 40 / DEC_DIGITS);
                               8304         [ -  + ]:           4312 :     if (val < 0)
                               8305                 :                :     {
 3313 andres@anarazel.de       8306                 :UBC           0 :         var->sign = NUMERIC_NEG;
                               8307                 :              0 :         uval = -val;
                               8308                 :                :     }
                               8309                 :                :     else
                               8310                 :                :     {
 3313 andres@anarazel.de       8311                 :CBC        4312 :         var->sign = NUMERIC_POS;
                               8312                 :           4312 :         uval = val;
                               8313                 :                :     }
                               8314                 :           4312 :     var->dscale = 0;
                               8315         [ +  + ]:           4312 :     if (val == 0)
                               8316                 :                :     {
                               8317                 :             65 :         var->ndigits = 0;
                               8318                 :             65 :         var->weight = 0;
                               8319                 :             65 :         return;
                               8320                 :                :     }
                               8321                 :           4247 :     ptr = var->digits + var->ndigits;
                               8322                 :           4247 :     ndigits = 0;
                               8323                 :                :     do
                               8324                 :                :     {
                               8325                 :          22520 :         ptr--;
                               8326                 :          22520 :         ndigits++;
                               8327                 :          22520 :         newuval = uval / NBASE;
                               8328                 :          22520 :         *ptr = uval - newuval * NBASE;
                               8329                 :          22520 :         uval = newuval;
                               8330         [ +  + ]:          22520 :     } while (uval);
                               8331                 :           4247 :     var->digits = ptr;
                               8332                 :           4247 :     var->ndigits = ndigits;
                               8333                 :           4247 :     var->weight = ndigits - 1;
                               8334                 :                : }
                               8335                 :                : #endif
                               8336                 :                : 
                               8337                 :                : /*
                               8338                 :                :  * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
                               8339                 :                :  */
                               8340                 :                : static double
 2408                          8341                 :           1791 : numericvar_to_double_no_overflow(const NumericVar *var)
                               8342                 :                : {
                               8343                 :                :     char       *tmp;
                               8344                 :                :     double      val;
                               8345                 :                :     char       *endptr;
                               8346                 :                : 
 4162 heikki.linnakangas@i     8347                 :           1791 :     tmp = get_str_from_var(var);
                               8348                 :                : 
                               8349                 :                :     /* unlike float8in, we ignore ERANGE from strtod */
 7865 tgl@sss.pgh.pa.us        8350                 :           1791 :     val = strtod(tmp, &endptr);
                               8351         [ -  + ]:           1791 :     if (*endptr != '\0')
                               8352                 :                :     {
                               8353                 :                :         /* shouldn't happen ... */
 7567 tgl@sss.pgh.pa.us        8354         [ #  # ]:UBC           0 :         ereport(ERROR,
                               8355                 :                :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               8356                 :                :                  errmsg("invalid input syntax for type %s: \"%s\"",
                               8357                 :                :                         "double precision", tmp)));
                               8358                 :                :     }
                               8359                 :                : 
 7865 tgl@sss.pgh.pa.us        8360                 :CBC        1791 :     pfree(tmp);
                               8361                 :                : 
                               8362                 :           1791 :     return val;
                               8363                 :                : }
                               8364                 :                : 
                               8365                 :                : 
                               8366                 :                : /*
                               8367                 :                :  * cmp_var() -
                               8368                 :                :  *
                               8369                 :                :  *  Compare two values on variable level.  We assume zeroes have been
                               8370                 :                :  *  truncated to no digits.
                               8371                 :                :  */
                               8372                 :                : static int
 2408 andres@anarazel.de       8373                 :          25093 : cmp_var(const NumericVar *var1, const NumericVar *var2)
                               8374                 :                : {
 6641 bruce@momjian.us         8375                 :          50186 :     return cmp_var_common(var1->digits, var1->ndigits,
                               8376                 :          25093 :                           var1->weight, var1->sign,
                               8377                 :          25093 :                           var2->digits, var2->ndigits,
                               8378                 :          25093 :                           var2->weight, var2->sign);
                               8379                 :                : }
                               8380                 :                : 
                               8381                 :                : /*
                               8382                 :                :  * cmp_var_common() -
                               8383                 :                :  *
                               8384                 :                :  *  Main routine of cmp_var(). This function can be used by both
                               8385                 :                :  *  NumericVar and Numeric.
                               8386                 :                :  */
                               8387                 :                : static int
                               8388                 :        3297724 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
                               8389                 :                :                int var1weight, int var1sign,
                               8390                 :                :                const NumericDigit *var2digits, int var2ndigits,
                               8391                 :                :                int var2weight, int var2sign)
                               8392                 :                : {
                               8393         [ +  + ]:        3297724 :     if (var1ndigits == 0)
                               8394                 :                :     {
                               8395         [ +  + ]:          98104 :         if (var2ndigits == 0)
 9237 JanWieck@Yahoo.com       8396                 :          83746 :             return 0;
 6641 bruce@momjian.us         8397         [ +  + ]:          14358 :         if (var2sign == NUMERIC_NEG)
 9237 JanWieck@Yahoo.com       8398                 :           2245 :             return 1;
                               8399                 :          12113 :         return -1;
                               8400                 :                :     }
 6641 bruce@momjian.us         8401         [ +  + ]:        3199620 :     if (var2ndigits == 0)
                               8402                 :                :     {
                               8403         [ +  + ]:          16972 :         if (var1sign == NUMERIC_POS)
 9237 JanWieck@Yahoo.com       8404                 :          13190 :             return 1;
                               8405                 :           3782 :         return -1;
                               8406                 :                :     }
                               8407                 :                : 
 6641 bruce@momjian.us         8408         [ +  + ]:        3182648 :     if (var1sign == NUMERIC_POS)
                               8409                 :                :     {
                               8410         [ +  + ]:        3135627 :         if (var2sign == NUMERIC_NEG)
 9237 JanWieck@Yahoo.com       8411                 :          13434 :             return 1;
 6641 bruce@momjian.us         8412                 :        3122193 :         return cmp_abs_common(var1digits, var1ndigits, var1weight,
                               8413                 :                :                               var2digits, var2ndigits, var2weight);
                               8414                 :                :     }
                               8415                 :                : 
                               8416         [ +  + ]:          47021 :     if (var2sign == NUMERIC_POS)
 9237 JanWieck@Yahoo.com       8417                 :          14561 :         return -1;
                               8418                 :                : 
 6641 bruce@momjian.us         8419                 :          32460 :     return cmp_abs_common(var2digits, var2ndigits, var2weight,
                               8420                 :                :                           var1digits, var1ndigits, var1weight);
                               8421                 :                : }
                               8422                 :                : 
                               8423                 :                : 
                               8424                 :                : /*
                               8425                 :                :  * add_var() -
                               8426                 :                :  *
                               8427                 :                :  *  Full version of add functionality on variable level (handling signs).
                               8428                 :                :  *  result might point to one of the operands too without danger.
                               8429                 :                :  */
                               8430                 :                : static void
 2408 andres@anarazel.de       8431                 :         248792 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               8432                 :                : {
                               8433                 :                :     /*
                               8434                 :                :      * Decide on the signs of the two variables what to do
                               8435                 :                :      */
 9237 JanWieck@Yahoo.com       8436         [ +  + ]:         248792 :     if (var1->sign == NUMERIC_POS)
                               8437                 :                :     {
                               8438         [ +  + ]:         248009 :         if (var2->sign == NUMERIC_POS)
                               8439                 :                :         {
                               8440                 :                :             /*
                               8441                 :                :              * Both are positive result = +(ABS(var1) + ABS(var2))
                               8442                 :                :              */
                               8443                 :         147896 :             add_abs(var1, var2, result);
                               8444                 :         147896 :             result->sign = NUMERIC_POS;
                               8445                 :                :         }
                               8446                 :                :         else
                               8447                 :                :         {
                               8448                 :                :             /*
                               8449                 :                :              * var1 is positive, var2 is negative Must compare absolute values
                               8450                 :                :              */
                               8451   [ +  +  +  - ]:         100113 :             switch (cmp_abs(var1, var2))
                               8452                 :                :             {
 8672 tgl@sss.pgh.pa.us        8453                 :             83 :                 case 0:
                               8454                 :                :                     /* ----------
                               8455                 :                :                      * ABS(var1) == ABS(var2)
                               8456                 :                :                      * result = ZERO
                               8457                 :                :                      * ----------
                               8458                 :                :                      */
 8853                          8459                 :             83 :                     zero_var(result);
 8091 bruce@momjian.us         8460                 :             83 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9091                          8461                 :             83 :                     break;
                               8462                 :                : 
 8672 tgl@sss.pgh.pa.us        8463                 :          93085 :                 case 1:
                               8464                 :                :                     /* ----------
                               8465                 :                :                      * ABS(var1) > ABS(var2)
                               8466                 :                :                      * result = +(ABS(var1) - ABS(var2))
                               8467                 :                :                      * ----------
                               8468                 :                :                      */
 9091 bruce@momjian.us         8469                 :          93085 :                     sub_abs(var1, var2, result);
                               8470                 :          93085 :                     result->sign = NUMERIC_POS;
                               8471                 :          93085 :                     break;
                               8472                 :                : 
 8672 tgl@sss.pgh.pa.us        8473                 :           6945 :                 case -1:
                               8474                 :                :                     /* ----------
                               8475                 :                :                      * ABS(var1) < ABS(var2)
                               8476                 :                :                      * result = -(ABS(var2) - ABS(var1))
                               8477                 :                :                      * ----------
                               8478                 :                :                      */
 9091 bruce@momjian.us         8479                 :           6945 :                     sub_abs(var2, var1, result);
                               8480                 :           6945 :                     result->sign = NUMERIC_NEG;
                               8481                 :           6945 :                     break;
                               8482                 :                :             }
                               8483                 :                :         }
                               8484                 :                :     }
                               8485                 :                :     else
                               8486                 :                :     {
 9237 JanWieck@Yahoo.com       8487         [ +  + ]:            783 :         if (var2->sign == NUMERIC_POS)
                               8488                 :                :         {
                               8489                 :                :             /* ----------
                               8490                 :                :              * var1 is negative, var2 is positive
                               8491                 :                :              * Must compare absolute values
                               8492                 :                :              * ----------
                               8493                 :                :              */
                               8494   [ +  +  +  - ]:            234 :             switch (cmp_abs(var1, var2))
                               8495                 :                :             {
 8672 tgl@sss.pgh.pa.us        8496                 :             15 :                 case 0:
                               8497                 :                :                     /* ----------
                               8498                 :                :                      * ABS(var1) == ABS(var2)
                               8499                 :                :                      * result = ZERO
                               8500                 :                :                      * ----------
                               8501                 :                :                      */
 8853                          8502                 :             15 :                     zero_var(result);
 8091 bruce@momjian.us         8503                 :             15 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9091                          8504                 :             15 :                     break;
                               8505                 :                : 
 8672 tgl@sss.pgh.pa.us        8506                 :            147 :                 case 1:
                               8507                 :                :                     /* ----------
                               8508                 :                :                      * ABS(var1) > ABS(var2)
                               8509                 :                :                      * result = -(ABS(var1) - ABS(var2))
                               8510                 :                :                      * ----------
                               8511                 :                :                      */
 9091 bruce@momjian.us         8512                 :            147 :                     sub_abs(var1, var2, result);
                               8513                 :            147 :                     result->sign = NUMERIC_NEG;
                               8514                 :            147 :                     break;
                               8515                 :                : 
 8672 tgl@sss.pgh.pa.us        8516                 :             72 :                 case -1:
                               8517                 :                :                     /* ----------
                               8518                 :                :                      * ABS(var1) < ABS(var2)
                               8519                 :                :                      * result = +(ABS(var2) - ABS(var1))
                               8520                 :                :                      * ----------
                               8521                 :                :                      */
 9091 bruce@momjian.us         8522                 :             72 :                     sub_abs(var2, var1, result);
                               8523                 :             72 :                     result->sign = NUMERIC_POS;
                               8524                 :             72 :                     break;
                               8525                 :                :             }
                               8526                 :                :         }
                               8527                 :                :         else
                               8528                 :                :         {
                               8529                 :                :             /* ----------
                               8530                 :                :              * Both are negative
                               8531                 :                :              * result = -(ABS(var1) + ABS(var2))
                               8532                 :                :              * ----------
                               8533                 :                :              */
 9237 JanWieck@Yahoo.com       8534                 :            549 :             add_abs(var1, var2, result);
                               8535                 :            549 :             result->sign = NUMERIC_NEG;
                               8536                 :                :         }
                               8537                 :                :     }
                               8538                 :         248792 : }
                               8539                 :                : 
                               8540                 :                : 
                               8541                 :                : /*
                               8542                 :                :  * sub_var() -
                               8543                 :                :  *
                               8544                 :                :  *  Full version of sub functionality on variable level (handling signs).
                               8545                 :                :  *  result might point to one of the operands too without danger.
                               8546                 :                :  */
                               8547                 :                : static void
 2408 andres@anarazel.de       8548                 :          94334 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               8549                 :                : {
                               8550                 :                :     /*
                               8551                 :                :      * Decide on the signs of the two variables what to do
                               8552                 :                :      */
 9237 JanWieck@Yahoo.com       8553         [ +  + ]:          94334 :     if (var1->sign == NUMERIC_POS)
                               8554                 :                :     {
                               8555         [ +  + ]:          92878 :         if (var2->sign == NUMERIC_NEG)
                               8556                 :                :         {
                               8557                 :                :             /* ----------
                               8558                 :                :              * var1 is positive, var2 is negative
                               8559                 :                :              * result = +(ABS(var1) + ABS(var2))
                               8560                 :                :              * ----------
                               8561                 :                :              */
                               8562                 :          16790 :             add_abs(var1, var2, result);
                               8563                 :          16790 :             result->sign = NUMERIC_POS;
                               8564                 :                :         }
                               8565                 :                :         else
                               8566                 :                :         {
                               8567                 :                :             /* ----------
                               8568                 :                :              * Both are positive
                               8569                 :                :              * Must compare absolute values
                               8570                 :                :              * ----------
                               8571                 :                :              */
                               8572   [ +  +  +  - ]:          76088 :             switch (cmp_abs(var1, var2))
                               8573                 :                :             {
 8672 tgl@sss.pgh.pa.us        8574                 :          14874 :                 case 0:
                               8575                 :                :                     /* ----------
                               8576                 :                :                      * ABS(var1) == ABS(var2)
                               8577                 :                :                      * result = ZERO
                               8578                 :                :                      * ----------
                               8579                 :                :                      */
 8853                          8580                 :          14874 :                     zero_var(result);
 8091 bruce@momjian.us         8581                 :          14874 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9091                          8582                 :          14874 :                     break;
                               8583                 :                : 
 8672 tgl@sss.pgh.pa.us        8584                 :          56177 :                 case 1:
                               8585                 :                :                     /* ----------
                               8586                 :                :                      * ABS(var1) > ABS(var2)
                               8587                 :                :                      * result = +(ABS(var1) - ABS(var2))
                               8588                 :                :                      * ----------
                               8589                 :                :                      */
 9091 bruce@momjian.us         8590                 :          56177 :                     sub_abs(var1, var2, result);
                               8591                 :          56177 :                     result->sign = NUMERIC_POS;
                               8592                 :          56177 :                     break;
                               8593                 :                : 
 8672 tgl@sss.pgh.pa.us        8594                 :           5037 :                 case -1:
                               8595                 :                :                     /* ----------
                               8596                 :                :                      * ABS(var1) < ABS(var2)
                               8597                 :                :                      * result = -(ABS(var2) - ABS(var1))
                               8598                 :                :                      * ----------
                               8599                 :                :                      */
 9091 bruce@momjian.us         8600                 :           5037 :                     sub_abs(var2, var1, result);
                               8601                 :           5037 :                     result->sign = NUMERIC_NEG;
                               8602                 :           5037 :                     break;
                               8603                 :                :             }
                               8604                 :                :         }
                               8605                 :                :     }
                               8606                 :                :     else
                               8607                 :                :     {
 9237 JanWieck@Yahoo.com       8608         [ +  + ]:           1456 :         if (var2->sign == NUMERIC_NEG)
                               8609                 :                :         {
                               8610                 :                :             /* ----------
                               8611                 :                :              * Both are negative
                               8612                 :                :              * Must compare absolute values
                               8613                 :                :              * ----------
                               8614                 :                :              */
                               8615   [ +  +  +  - ]:           1231 :             switch (cmp_abs(var1, var2))
                               8616                 :                :             {
 8672 tgl@sss.pgh.pa.us        8617                 :             83 :                 case 0:
                               8618                 :                :                     /* ----------
                               8619                 :                :                      * ABS(var1) == ABS(var2)
                               8620                 :                :                      * result = ZERO
                               8621                 :                :                      * ----------
                               8622                 :                :                      */
 8853                          8623                 :             83 :                     zero_var(result);
 8091 bruce@momjian.us         8624                 :             83 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9091                          8625                 :             83 :                     break;
                               8626                 :                : 
 8672 tgl@sss.pgh.pa.us        8627                 :            120 :                 case 1:
                               8628                 :                :                     /* ----------
                               8629                 :                :                      * ABS(var1) > ABS(var2)
                               8630                 :                :                      * result = -(ABS(var1) - ABS(var2))
                               8631                 :                :                      * ----------
                               8632                 :                :                      */
 9091 bruce@momjian.us         8633                 :            120 :                     sub_abs(var1, var2, result);
                               8634                 :            120 :                     result->sign = NUMERIC_NEG;
                               8635                 :            120 :                     break;
                               8636                 :                : 
 8672 tgl@sss.pgh.pa.us        8637                 :           1028 :                 case -1:
                               8638                 :                :                     /* ----------
                               8639                 :                :                      * ABS(var1) < ABS(var2)
                               8640                 :                :                      * result = +(ABS(var2) - ABS(var1))
                               8641                 :                :                      * ----------
                               8642                 :                :                      */
 9091 bruce@momjian.us         8643                 :           1028 :                     sub_abs(var2, var1, result);
                               8644                 :           1028 :                     result->sign = NUMERIC_POS;
                               8645                 :           1028 :                     break;
                               8646                 :                :             }
                               8647                 :                :         }
                               8648                 :                :         else
                               8649                 :                :         {
                               8650                 :                :             /* ----------
                               8651                 :                :              * var1 is negative, var2 is positive
                               8652                 :                :              * result = -(ABS(var1) + ABS(var2))
                               8653                 :                :              * ----------
                               8654                 :                :              */
 9237 JanWieck@Yahoo.com       8655                 :            225 :             add_abs(var1, var2, result);
                               8656                 :            225 :             result->sign = NUMERIC_NEG;
                               8657                 :                :         }
                               8658                 :                :     }
                               8659                 :          94334 : }
                               8660                 :                : 
                               8661                 :                : 
                               8662                 :                : /*
                               8663                 :                :  * mul_var() -
                               8664                 :                :  *
                               8665                 :                :  *  Multiplication on variable level. Product of var1 * var2 is stored
                               8666                 :                :  *  in result.  Result is rounded to no more than rscale fractional digits.
                               8667                 :                :  */
                               8668                 :                : static void
 2408 andres@anarazel.de       8669                 :         415251 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
                               8670                 :                :         int rscale)
                               8671                 :                : {
                               8672                 :                :     int         res_ndigits;
                               8673                 :                :     int         res_sign;
                               8674                 :                :     int         res_weight;
                               8675                 :                :     int         maxdigits;
                               8676                 :                :     int        *dig;
                               8677                 :                :     int         carry;
                               8678                 :                :     int         maxdig;
                               8679                 :                :     int         newdig;
                               8680                 :                :     int         var1ndigits;
                               8681                 :                :     int         var2ndigits;
                               8682                 :                :     NumericDigit *var1digits;
                               8683                 :                :     NumericDigit *var2digits;
                               8684                 :                :     NumericDigit *res_digits;
                               8685                 :                :     int         i,
                               8686                 :                :                 i1,
                               8687                 :                :                 i2;
                               8688                 :                : 
                               8689                 :                :     /*
                               8690                 :                :      * Arrange for var1 to be the shorter of the two numbers.  This improves
                               8691                 :                :      * performance because the inner multiplication loop is much simpler than
                               8692                 :                :      * the outer loop, so it's better to have a smaller number of iterations
                               8693                 :                :      * of the outer loop.  This also reduces the number of times that the
                               8694                 :                :      * accumulator array needs to be normalized.
                               8695                 :                :      */
 3074 tgl@sss.pgh.pa.us        8696         [ +  + ]:         415251 :     if (var1->ndigits > var2->ndigits)
                               8697                 :                :     {
 2408 andres@anarazel.de       8698                 :           7386 :         const NumericVar *tmp = var1;
                               8699                 :                : 
 3074 tgl@sss.pgh.pa.us        8700                 :           7386 :         var1 = var2;
                               8701                 :           7386 :         var2 = tmp;
                               8702                 :                :     }
                               8703                 :                : 
                               8704                 :                :     /* copy these values into local vars for speed in inner loop */
                               8705                 :         415251 :     var1ndigits = var1->ndigits;
                               8706                 :         415251 :     var2ndigits = var2->ndigits;
                               8707                 :         415251 :     var1digits = var1->digits;
                               8708                 :         415251 :     var2digits = var2->digits;
                               8709                 :                : 
 7695                          8710   [ +  +  -  + ]:         415251 :     if (var1ndigits == 0 || var2ndigits == 0)
                               8711                 :                :     {
                               8712                 :                :         /* one or both inputs is zero; so is result */
                               8713                 :            856 :         zero_var(result);
                               8714                 :            856 :         result->dscale = rscale;
                               8715                 :            856 :         return;
                               8716                 :                :     }
                               8717                 :                : 
                               8718                 :                :     /* Determine result sign and (maximum possible) weight */
 9237 JanWieck@Yahoo.com       8719         [ +  + ]:         414395 :     if (var1->sign == var2->sign)
                               8720                 :         413130 :         res_sign = NUMERIC_POS;
                               8721                 :                :     else
                               8722                 :           1265 :         res_sign = NUMERIC_NEG;
 7695 tgl@sss.pgh.pa.us        8723                 :         414395 :     res_weight = var1->weight + var2->weight + 2;
                               8724                 :                : 
                               8725                 :                :     /*
                               8726                 :                :      * Determine the number of result digits to compute.  If the exact result
                               8727                 :                :      * would have more than rscale fractional digits, truncate the computation
                               8728                 :                :      * with MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that
                               8729                 :                :      * would only contribute to the right of that.  (This will give the exact
                               8730                 :                :      * rounded-to-rscale answer unless carries out of the ignored positions
                               8731                 :                :      * would have propagated through more than MUL_GUARD_DIGITS digits.)
                               8732                 :                :      *
                               8733                 :                :      * Note: an exact computation could not produce more than var1ndigits +
                               8734                 :                :      * var2ndigits digits, but we allocate one extra output digit in case
                               8735                 :                :      * rscale-driven rounding produces a carry out of the highest exact digit.
                               8736                 :                :      */
                               8737                 :         414395 :     res_ndigits = var1ndigits + var2ndigits + 1;
 3074                          8738                 :         414395 :     maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
                               8739                 :                :         MUL_GUARD_DIGITS;
                               8740                 :         414395 :     res_ndigits = Min(res_ndigits, maxdigits);
                               8741                 :                : 
                               8742         [ +  + ]:         414395 :     if (res_ndigits < 3)
                               8743                 :                :     {
                               8744                 :                :         /* All input digits will be ignored; so result is zero */
                               8745                 :              6 :         zero_var(result);
                               8746                 :              6 :         result->dscale = rscale;
                               8747                 :              6 :         return;
                               8748                 :                :     }
                               8749                 :                : 
                               8750                 :                :     /*
                               8751                 :                :      * We do the arithmetic in an array "dig[]" of signed int's.  Since
                               8752                 :                :      * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
                               8753                 :                :      * to avoid normalizing carries immediately.
                               8754                 :                :      *
                               8755                 :                :      * maxdig tracks the maximum possible value of any dig[] entry; when this
                               8756                 :                :      * threatens to exceed INT_MAX, we take the time to propagate carries.
                               8757                 :                :      * Furthermore, we need to ensure that overflow doesn't occur during the
                               8758                 :                :      * carry propagation passes either.  The carry values could be as much as
                               8759                 :                :      * INT_MAX/NBASE, so really we must normalize when digits threaten to
                               8760                 :                :      * exceed INT_MAX - INT_MAX/NBASE.
                               8761                 :                :      *
                               8762                 :                :      * To avoid overflow in maxdig itself, it actually represents the max
                               8763                 :                :      * possible value divided by NBASE-1, ie, at the top of the loop it is
                               8764                 :                :      * known that no dig[] entry exceeds maxdig * (NBASE-1).
                               8765                 :                :      */
 7695                          8766                 :         414389 :     dig = (int *) palloc0(res_ndigits * sizeof(int));
                               8767                 :         414389 :     maxdig = 0;
                               8768                 :                : 
                               8769                 :                :     /*
                               8770                 :                :      * The least significant digits of var1 should be ignored if they don't
                               8771                 :                :      * contribute directly to the first res_ndigits digits of the result that
                               8772                 :                :      * we are computing.
                               8773                 :                :      *
                               8774                 :                :      * Digit i1 of var1 and digit i2 of var2 are multiplied and added to digit
                               8775                 :                :      * i1+i2+2 of the accumulator array, so we need only consider digits of
                               8776                 :                :      * var1 for which i1 <= res_ndigits - 3.
                               8777                 :                :      */
 3074                          8778         [ +  + ]:        2316712 :     for (i1 = Min(var1ndigits - 1, res_ndigits - 3); i1 >= 0; i1--)
                               8779                 :                :     {
  777 dean.a.rasheed@gmail     8780                 :        1902323 :         NumericDigit var1digit = var1digits[i1];
                               8781                 :                : 
 7695 tgl@sss.pgh.pa.us        8782         [ +  + ]:        1902323 :         if (var1digit == 0)
                               8783                 :        1179720 :             continue;
                               8784                 :                : 
                               8785                 :                :         /* Time to normalize? */
                               8786                 :         722603 :         maxdig += var1digit;
 3128                          8787         [ +  + ]:         722603 :         if (maxdig > (INT_MAX - INT_MAX / NBASE) / (NBASE - 1))
                               8788                 :                :         {
                               8789                 :                :             /* Yes, do it */
 7695                          8790                 :           4572 :             carry = 0;
 7559 bruce@momjian.us         8791         [ +  + ]:       22905348 :             for (i = res_ndigits - 1; i >= 0; i--)
                               8792                 :                :             {
 7695 tgl@sss.pgh.pa.us        8793                 :       22900776 :                 newdig = dig[i] + carry;
                               8794         [ +  + ]:       22900776 :                 if (newdig >= NBASE)
                               8795                 :                :                 {
 7559 bruce@momjian.us         8796                 :       11532801 :                     carry = newdig / NBASE;
                               8797                 :       11532801 :                     newdig -= carry * NBASE;
                               8798                 :                :                 }
                               8799                 :                :                 else
 7695 tgl@sss.pgh.pa.us        8800                 :       11367975 :                     carry = 0;
                               8801                 :       22900776 :                 dig[i] = newdig;
                               8802                 :                :             }
                               8803         [ -  + ]:           4572 :             Assert(carry == 0);
                               8804                 :                :             /* Reset maxdig to indicate new worst-case */
                               8805                 :           4572 :             maxdig = 1 + var1digit;
                               8806                 :                :         }
                               8807                 :                : 
                               8808                 :                :         /*
                               8809                 :                :          * Add the appropriate multiple of var2 into the accumulator.
                               8810                 :                :          *
                               8811                 :                :          * As above, digits of var2 can be ignored if they don't contribute,
                               8812                 :                :          * so we only include digits for which i1+i2+2 < res_ndigits.
                               8813                 :                :          *
                               8814                 :                :          * This inner loop is the performance bottleneck for multiplication,
                               8815                 :                :          * so we want to keep it simple enough so that it can be
                               8816                 :                :          * auto-vectorized.  Accordingly, process the digits left-to-right
                               8817                 :                :          * even though schoolbook multiplication would suggest right-to-left.
                               8818                 :                :          * Since we aren't propagating carries in this loop, the order does
                               8819                 :                :          * not matter.
                               8820                 :                :          */
                               8821                 :                :         {
 1315                          8822                 :         722603 :             int         i2limit = Min(var2ndigits, res_ndigits - i1 - 2);
                               8823                 :         722603 :             int        *dig_i1_2 = &dig[i1 + 2];
                               8824                 :                : 
                               8825         [ +  + ]:      249559007 :             for (i2 = 0; i2 < i2limit; i2++)
                               8826                 :      248836404 :                 dig_i1_2[i2] += var1digit * var2digits[i2];
                               8827                 :                :         }
                               8828                 :                :     }
                               8829                 :                : 
                               8830                 :                :     /*
                               8831                 :                :      * Now we do a final carry propagation pass to normalize the result, which
                               8832                 :                :      * we combine with storing the result digits into the output. Note that
                               8833                 :                :      * this is still done at full precision w/guard digits.
                               8834                 :                :      */
 7695                          8835                 :         414389 :     alloc_var(result, res_ndigits);
                               8836                 :         414389 :     res_digits = result->digits;
                               8837                 :         414389 :     carry = 0;
 7559 bruce@momjian.us         8838         [ +  + ]:        5120661 :     for (i = res_ndigits - 1; i >= 0; i--)
                               8839                 :                :     {
 7695 tgl@sss.pgh.pa.us        8840                 :        4706272 :         newdig = dig[i] + carry;
                               8841         [ +  + ]:        4706272 :         if (newdig >= NBASE)
                               8842                 :                :         {
 7559 bruce@momjian.us         8843                 :         991612 :             carry = newdig / NBASE;
                               8844                 :         991612 :             newdig -= carry * NBASE;
                               8845                 :                :         }
                               8846                 :                :         else
 7695 tgl@sss.pgh.pa.us        8847                 :        3714660 :             carry = 0;
                               8848                 :        4706272 :         res_digits[i] = newdig;
                               8849                 :                :     }
                               8850         [ -  + ]:         414389 :     Assert(carry == 0);
                               8851                 :                : 
                               8852                 :         414389 :     pfree(dig);
                               8853                 :                : 
                               8854                 :                :     /*
                               8855                 :                :      * Finally, round the result to the requested precision.
                               8856                 :                :      */
 9091 bruce@momjian.us         8857                 :         414389 :     result->weight = res_weight;
                               8858                 :         414389 :     result->sign = res_sign;
                               8859                 :                : 
                               8860                 :                :     /* Round to target rscale (and set result->dscale) */
 7695 tgl@sss.pgh.pa.us        8861                 :         414389 :     round_var(result, rscale);
                               8862                 :                : 
                               8863                 :                :     /* Strip leading and trailing zeroes */
                               8864                 :         414389 :     strip_var(result);
                               8865                 :                : }
                               8866                 :                : 
                               8867                 :                : 
                               8868                 :                : /*
                               8869                 :                :  * div_var() -
                               8870                 :                :  *
                               8871                 :                :  *  Division on variable level. Quotient of var1 / var2 is stored in result.
                               8872                 :                :  *  The quotient is figured to exactly rscale fractional digits.
                               8873                 :                :  *  If round is true, it is rounded at the rscale'th digit; if false, it
                               8874                 :                :  *  is truncated (towards zero) at that digit.
                               8875                 :                :  */
                               8876                 :                : static void
 2408 andres@anarazel.de       8877                 :         104566 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
                               8878                 :                :         int rscale, bool round)
                               8879                 :                : {
                               8880                 :                :     int         div_ndigits;
                               8881                 :                :     int         res_ndigits;
                               8882                 :                :     int         res_sign;
                               8883                 :                :     int         res_weight;
                               8884                 :                :     int         carry;
                               8885                 :                :     int         borrow;
                               8886                 :                :     int         divisor1;
                               8887                 :                :     int         divisor2;
                               8888                 :                :     NumericDigit *dividend;
                               8889                 :                :     NumericDigit *divisor;
                               8890                 :                :     NumericDigit *res_digits;
                               8891                 :                :     int         i;
                               8892                 :                :     int         j;
                               8893                 :                : 
                               8894                 :                :     /* copy these values into local vars for speed in inner loop */
 5854 tgl@sss.pgh.pa.us        8895                 :         104566 :     int         var1ndigits = var1->ndigits;
                               8896                 :         104566 :     int         var2ndigits = var2->ndigits;
                               8897                 :                : 
                               8898                 :                :     /*
                               8899                 :                :      * First of all division by zero check; we must not be handed an
                               8900                 :                :      * unnormalized divisor.
                               8901                 :                :      */
                               8902   [ +  +  -  + ]:         104566 :     if (var2ndigits == 0 || var2->digits[0] == 0)
                               8903         [ +  - ]:             28 :         ereport(ERROR,
                               8904                 :                :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
                               8905                 :                :                  errmsg("division by zero")));
                               8906                 :                : 
                               8907                 :                :     /*
                               8908                 :                :      * If the divisor has just one or two digits, delegate to div_var_int(),
                               8909                 :                :      * which uses fast short division.
                               8910                 :                :      *
                               8911                 :                :      * Similarly, on platforms with 128-bit integer support, delegate to
                               8912                 :                :      * div_var_int64() for divisors with three or four digits.
                               8913                 :                :      */
  777 dean.a.rasheed@gmail     8914         [ +  + ]:         104538 :     if (var2ndigits <= 2)
                               8915                 :                :     {
                               8916                 :                :         int         idivisor;
                               8917                 :                :         int         idivisor_weight;
                               8918                 :                : 
                               8919                 :         102649 :         idivisor = var2->digits[0];
                               8920                 :         102649 :         idivisor_weight = var2->weight;
                               8921         [ +  + ]:         102649 :         if (var2ndigits == 2)
                               8922                 :                :         {
                               8923                 :           2326 :             idivisor = idivisor * NBASE + var2->digits[1];
                               8924                 :           2326 :             idivisor_weight--;
                               8925                 :                :         }
                               8926         [ +  + ]:         102649 :         if (var2->sign == NUMERIC_NEG)
                               8927                 :            243 :             idivisor = -idivisor;
                               8928                 :                : 
                               8929                 :         102649 :         div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
                               8930                 :         102649 :         return;
                               8931                 :                :     }
                               8932                 :                : #ifdef HAVE_INT128
  447                          8933         [ +  + ]:           1889 :     if (var2ndigits <= 4)
                               8934                 :                :     {
                               8935                 :                :         int64       idivisor;
                               8936                 :                :         int         idivisor_weight;
                               8937                 :                : 
                               8938                 :            249 :         idivisor = var2->digits[0];
                               8939                 :            249 :         idivisor_weight = var2->weight;
                               8940         [ +  + ]:            936 :         for (i = 1; i < var2ndigits; i++)
                               8941                 :                :         {
                               8942                 :            687 :             idivisor = idivisor * NBASE + var2->digits[i];
                               8943                 :            687 :             idivisor_weight--;
                               8944                 :                :         }
                               8945         [ +  + ]:            249 :         if (var2->sign == NUMERIC_NEG)
                               8946                 :             60 :             idivisor = -idivisor;
                               8947                 :                : 
                               8948                 :            249 :         div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
                               8949                 :            249 :         return;
                               8950                 :                :     }
                               8951                 :                : #endif
                               8952                 :                : 
                               8953                 :                :     /*
                               8954                 :                :      * Otherwise, perform full long division.
                               8955                 :                :      */
                               8956                 :                : 
                               8957                 :                :     /* Result zero check */
 5854 tgl@sss.pgh.pa.us        8958         [ +  + ]:           1640 :     if (var1ndigits == 0)
                               8959                 :                :     {
                               8960                 :             12 :         zero_var(result);
                               8961                 :             12 :         result->dscale = rscale;
                               8962                 :             12 :         return;
                               8963                 :                :     }
                               8964                 :                : 
                               8965                 :                :     /*
                               8966                 :                :      * Determine the result sign, weight and number of digits to calculate.
                               8967                 :                :      * The weight figured here is correct if the emitted quotient has no
                               8968                 :                :      * leading zero digits; otherwise strip_var() will fix things up.
                               8969                 :                :      */
                               8970         [ +  + ]:           1628 :     if (var1->sign == var2->sign)
                               8971                 :           1598 :         res_sign = NUMERIC_POS;
                               8972                 :                :     else
                               8973                 :             30 :         res_sign = NUMERIC_NEG;
                               8974                 :           1628 :     res_weight = var1->weight - var2->weight;
                               8975                 :                :     /* The number of accurate result digits we need to produce: */
                               8976                 :           1628 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               8977                 :                :     /* ... but always at least 1 */
                               8978                 :           1628 :     res_ndigits = Max(res_ndigits, 1);
                               8979                 :                :     /* If rounding needed, figure one more digit to ensure correct result */
                               8980         [ +  - ]:           1628 :     if (round)
                               8981                 :           1628 :         res_ndigits++;
                               8982                 :                : 
                               8983                 :                :     /*
                               8984                 :                :      * The working dividend normally requires res_ndigits + var2ndigits
                               8985                 :                :      * digits, but make it at least var1ndigits so we can load all of var1
                               8986                 :                :      * into it.  (There will be an additional digit dividend[0] in the
                               8987                 :                :      * dividend space, but for consistency with Knuth's notation we don't
                               8988                 :                :      * count that in div_ndigits.)
                               8989                 :                :      */
                               8990                 :           1628 :     div_ndigits = res_ndigits + var2ndigits;
                               8991                 :           1628 :     div_ndigits = Max(div_ndigits, var1ndigits);
                               8992                 :                : 
                               8993                 :                :     /*
                               8994                 :                :      * We need a workspace with room for the working dividend (div_ndigits+1
                               8995                 :                :      * digits) plus room for the possibly-normalized divisor (var2ndigits
                               8996                 :                :      * digits).  It is convenient also to have a zero at divisor[0] with the
                               8997                 :                :      * actual divisor data in divisor[1 .. var2ndigits].  Transferring the
                               8998                 :                :      * digits into the workspace also allows us to realloc the result (which
                               8999                 :                :      * might be the same as either input var) before we begin the main loop.
                               9000                 :                :      * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
                               9001                 :                :      * any additional dividend positions beyond var1ndigits, start out 0.
                               9002                 :                :      */
                               9003                 :                :     dividend = (NumericDigit *)
                               9004                 :           1628 :         palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
                               9005                 :           1628 :     divisor = dividend + (div_ndigits + 1);
                               9006                 :           1628 :     memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
                               9007                 :           1628 :     memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
                               9008                 :                : 
                               9009                 :                :     /*
                               9010                 :                :      * Now we can realloc the result to hold the generated quotient digits.
                               9011                 :                :      */
                               9012                 :           1628 :     alloc_var(result, res_ndigits);
                               9013                 :           1628 :     res_digits = result->digits;
                               9014                 :                : 
                               9015                 :                :     /*
                               9016                 :                :      * The full multiple-place algorithm is taken from Knuth volume 2,
                               9017                 :                :      * Algorithm 4.3.1D.
                               9018                 :                :      *
                               9019                 :                :      * We need the first divisor digit to be >= NBASE/2.  If it isn't, make it
                               9020                 :                :      * so by scaling up both the divisor and dividend by the factor "d".  (The
                               9021                 :                :      * reason for allocating dividend[0] above is to leave room for possible
                               9022                 :                :      * carry here.)
                               9023                 :                :      */
  703                          9024         [ +  - ]:           1628 :     if (divisor[1] < HALF_NBASE)
                               9025                 :                :     {
                               9026                 :           1628 :         int         d = NBASE / (divisor[1] + 1);
                               9027                 :                : 
                               9028                 :           1628 :         carry = 0;
                               9029         [ +  + ]:          13853 :         for (i = var2ndigits; i > 0; i--)
                               9030                 :                :         {
                               9031                 :          12225 :             carry += divisor[i] * d;
                               9032                 :          12225 :             divisor[i] = carry % NBASE;
                               9033                 :          12225 :             carry = carry / NBASE;
                               9034                 :                :         }
                               9035         [ -  + ]:           1628 :         Assert(carry == 0);
                               9036                 :           1628 :         carry = 0;
                               9037                 :                :         /* at this point only var1ndigits of dividend can be nonzero */
                               9038         [ +  + ]:          13867 :         for (i = var1ndigits; i >= 0; i--)
                               9039                 :                :         {
                               9040                 :          12239 :             carry += dividend[i] * d;
                               9041                 :          12239 :             dividend[i] = carry % NBASE;
                               9042                 :          12239 :             carry = carry / NBASE;
                               9043                 :                :         }
                               9044         [ -  + ]:           1628 :         Assert(carry == 0);
                               9045         [ -  + ]:           1628 :         Assert(divisor[1] >= HALF_NBASE);
                               9046                 :                :     }
                               9047                 :                :     /* First 2 divisor digits are used repeatedly in main loop */
                               9048                 :           1628 :     divisor1 = divisor[1];
                               9049                 :           1628 :     divisor2 = divisor[2];
                               9050                 :                : 
                               9051                 :                :     /*
                               9052                 :                :      * Begin the main loop.  Each iteration of this loop produces the j'th
                               9053                 :                :      * quotient digit by dividing dividend[j .. j + var2ndigits] by the
                               9054                 :                :      * divisor; this is essentially the same as the common manual procedure
                               9055                 :                :      * for long division.
                               9056                 :                :      */
                               9057         [ +  + ]:          12300 :     for (j = 0; j < res_ndigits; j++)
                               9058                 :                :     {
                               9059                 :                :         /* Estimate quotient digit from the first two dividend digits */
                               9060                 :          10672 :         int         next2digits = dividend[j] * NBASE + dividend[j + 1];
                               9061                 :                :         int         qhat;
                               9062                 :                : 
                               9063                 :                :         /*
                               9064                 :                :          * If next2digits are 0, then quotient digit must be 0 and there's no
                               9065                 :                :          * need to adjust the working dividend.  It's worth testing here to
                               9066                 :                :          * fall out ASAP when processing trailing zeroes in a dividend.
                               9067                 :                :          */
                               9068         [ +  + ]:          10672 :         if (next2digits == 0)
                               9069                 :                :         {
                               9070                 :             36 :             res_digits[j] = 0;
                               9071                 :             36 :             continue;
                               9072                 :                :         }
                               9073                 :                : 
                               9074         [ +  + ]:          10636 :         if (dividend[j] == divisor1)
                               9075                 :             60 :             qhat = NBASE - 1;
                               9076                 :                :         else
                               9077                 :          10576 :             qhat = next2digits / divisor1;
                               9078                 :                : 
                               9079                 :                :         /*
                               9080                 :                :          * Adjust quotient digit if it's too large.  Knuth proves that after
                               9081                 :                :          * this step, the quotient digit will be either correct or just one
                               9082                 :                :          * too large.  (Note: it's OK to use dividend[j+2] here because we
                               9083                 :                :          * know the divisor length is at least 2.)
                               9084                 :                :          */
                               9085                 :          10636 :         while (divisor2 * qhat >
                               9086         [ +  + ]:          12471 :                (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
                               9087                 :           1835 :             qhat--;
                               9088                 :                : 
                               9089                 :                :         /* As above, need do nothing more when quotient digit is 0 */
                               9090         [ +  + ]:          10636 :         if (qhat > 0)
                               9091                 :                :         {
                               9092                 :           9832 :             NumericDigit *dividend_j = &dividend[j];
                               9093                 :                : 
                               9094                 :                :             /*
                               9095                 :                :              * Multiply the divisor by qhat, and subtract that from the
                               9096                 :                :              * working dividend.  The multiplication and subtraction are
                               9097                 :                :              * folded together here, noting that qhat <= NBASE (since it might
                               9098                 :                :              * be one too large), and so the intermediate result "tmp_result"
                               9099                 :                :              * is in the range [-NBASE^2, NBASE - 1], and "borrow" is in the
                               9100                 :                :              * range [0, NBASE].
                               9101                 :                :              */
                               9102                 :           9832 :             borrow = 0;
                               9103         [ +  + ]:          95930 :             for (i = var2ndigits; i >= 0; i--)
                               9104                 :                :             {
                               9105                 :                :                 int         tmp_result;
                               9106                 :                : 
                               9107                 :          86098 :                 tmp_result = dividend_j[i] - borrow - divisor[i] * qhat;
                               9108                 :          86098 :                 borrow = (NBASE - 1 - tmp_result) / NBASE;
                               9109                 :          86098 :                 dividend_j[i] = tmp_result + borrow * NBASE;
                               9110                 :                :             }
                               9111                 :                : 
                               9112                 :                :             /*
                               9113                 :                :              * If we got a borrow out of the top dividend digit, then indeed
                               9114                 :                :              * qhat was one too large.  Fix it, and add back the divisor to
                               9115                 :                :              * correct the working dividend.  (Knuth proves that this will
                               9116                 :                :              * occur only about 3/NBASE of the time; hence, it's a good idea
                               9117                 :                :              * to test this code with small NBASE to be sure this section gets
                               9118                 :                :              * exercised.)
                               9119                 :                :              */
                               9120         [ +  + ]:           9832 :             if (borrow)
                               9121                 :                :             {
                               9122                 :             14 :                 qhat--;
                               9123                 :             14 :                 carry = 0;
 5854                          9124         [ +  + ]:           1163 :                 for (i = var2ndigits; i >= 0; i--)
                               9125                 :                :                 {
  703                          9126                 :           1149 :                     carry += dividend_j[i] + divisor[i];
                               9127         [ +  + ]:           1149 :                     if (carry >= NBASE)
                               9128                 :                :                     {
                               9129                 :           1050 :                         dividend_j[i] = carry - NBASE;
                               9130                 :           1050 :                         carry = 1;
                               9131                 :                :                     }
                               9132                 :                :                     else
                               9133                 :                :                     {
                               9134                 :             99 :                         dividend_j[i] = carry;
                               9135                 :             99 :                         carry = 0;
                               9136                 :                :                     }
                               9137                 :                :                 }
                               9138                 :                :                 /* A carry should occur here to cancel the borrow above */
                               9139         [ -  + ]:             14 :                 Assert(carry == 1);
                               9140                 :                :             }
                               9141                 :                :         }
                               9142                 :                : 
                               9143                 :                :         /* And we're done with this quotient digit */
                               9144                 :          10636 :         res_digits[j] = qhat;
                               9145                 :                :     }
                               9146                 :                : 
 5854                          9147                 :           1628 :     pfree(dividend);
                               9148                 :                : 
                               9149                 :                :     /*
                               9150                 :                :      * Finally, round or truncate the result to the requested precision.
                               9151                 :                :      */
                               9152                 :           1628 :     result->weight = res_weight;
                               9153                 :           1628 :     result->sign = res_sign;
                               9154                 :                : 
                               9155                 :                :     /* Round or truncate to target rscale (and set result->dscale) */
                               9156         [ +  - ]:           1628 :     if (round)
                               9157                 :           1628 :         round_var(result, rscale);
                               9158                 :                :     else
 5854 tgl@sss.pgh.pa.us        9159                 :UBC           0 :         trunc_var(result, rscale);
                               9160                 :                : 
                               9161                 :                :     /* Strip leading and trailing zeroes */
 5854 tgl@sss.pgh.pa.us        9162                 :CBC        1628 :     strip_var(result);
                               9163                 :                : }
                               9164                 :                : 
                               9165                 :                : 
                               9166                 :                : /*
                               9167                 :                :  * div_var_fast() -
                               9168                 :                :  *
                               9169                 :                :  *  This has the same API as div_var, but is implemented using the division
                               9170                 :                :  *  algorithm from the "FM" library, rather than Knuth's schoolbook-division
                               9171                 :                :  *  approach.  This is significantly faster but can produce inaccurate
                               9172                 :                :  *  results, because it sometimes has to propagate rounding to the left,
                               9173                 :                :  *  and so we can never be entirely sure that we know the requested digits
                               9174                 :                :  *  exactly.  We compute DIV_GUARD_DIGITS extra digits, but there is
                               9175                 :                :  *  no certainty that that's enough.  We use this only in the transcendental
                               9176                 :                :  *  function calculation routines, where everything is approximate anyway.
                               9177                 :                :  *
                               9178                 :                :  *  Although we provide a "round" argument for consistency with div_var,
                               9179                 :                :  *  it is unwise to use this function with round=false.  In truncation mode
                               9180                 :                :  *  it is possible to get a result with no significant digits, for example
                               9181                 :                :  *  with rscale=0 we might compute 0.99999... and truncate that to 0 when
                               9182                 :                :  *  the correct answer is 1.
                               9183                 :                :  */
                               9184                 :                : static void
 2408 andres@anarazel.de       9185                 :           2958 : div_var_fast(const NumericVar *var1, const NumericVar *var2,
                               9186                 :                :              NumericVar *result, int rscale, bool round)
                               9187                 :                : {
                               9188                 :                :     int         div_ndigits;
                               9189                 :                :     int         load_ndigits;
                               9190                 :                :     int         res_sign;
                               9191                 :                :     int         res_weight;
                               9192                 :                :     int        *div;
                               9193                 :                :     int         qdigit;
                               9194                 :                :     int         carry;
                               9195                 :                :     int         maxdiv;
                               9196                 :                :     int         newdig;
                               9197                 :                :     NumericDigit *res_digits;
                               9198                 :                :     double      fdividend,
                               9199                 :                :                 fdivisor,
                               9200                 :                :                 fdivisorinverse,
                               9201                 :                :                 fquotient;
                               9202                 :                :     int         qi;
                               9203                 :                :     int         i;
                               9204                 :                : 
                               9205                 :                :     /* copy these values into local vars for speed in inner loop */
 7695 tgl@sss.pgh.pa.us        9206                 :           2958 :     int         var1ndigits = var1->ndigits;
                               9207                 :           2958 :     int         var2ndigits = var2->ndigits;
                               9208                 :           2958 :     NumericDigit *var1digits = var1->digits;
                               9209                 :           2958 :     NumericDigit *var2digits = var2->digits;
                               9210                 :                : 
                               9211                 :                :     /*
                               9212                 :                :      * First of all division by zero check; we must not be handed an
                               9213                 :                :      * unnormalized divisor.
                               9214                 :                :      */
                               9215   [ +  +  -  + ]:           2958 :     if (var2ndigits == 0 || var2digits[0] == 0)
 7567                          9216         [ +  - ]:              3 :         ereport(ERROR,
                               9217                 :                :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
                               9218                 :                :                  errmsg("division by zero")));
                               9219                 :                : 
                               9220                 :                :     /*
                               9221                 :                :      * If the divisor has just one or two digits, delegate to div_var_int(),
                               9222                 :                :      * which uses fast short division.
                               9223                 :                :      *
                               9224                 :                :      * Similarly, on platforms with 128-bit integer support, delegate to
                               9225                 :                :      * div_var_int64() for divisors with three or four digits.
                               9226                 :                :      */
  777 dean.a.rasheed@gmail     9227         [ +  + ]:           2955 :     if (var2ndigits <= 2)
                               9228                 :                :     {
                               9229                 :                :         int         idivisor;
                               9230                 :                :         int         idivisor_weight;
                               9231                 :                : 
                               9232                 :            264 :         idivisor = var2->digits[0];
                               9233                 :            264 :         idivisor_weight = var2->weight;
                               9234         [ -  + ]:            264 :         if (var2ndigits == 2)
                               9235                 :                :         {
  777 dean.a.rasheed@gmail     9236                 :UBC           0 :             idivisor = idivisor * NBASE + var2->digits[1];
                               9237                 :              0 :             idivisor_weight--;
                               9238                 :                :         }
  777 dean.a.rasheed@gmail     9239         [ -  + ]:CBC         264 :         if (var2->sign == NUMERIC_NEG)
  777 dean.a.rasheed@gmail     9240                 :UBC           0 :             idivisor = -idivisor;
                               9241                 :                : 
  777 dean.a.rasheed@gmail     9242                 :CBC         264 :         div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
                               9243                 :            264 :         return;
                               9244                 :                :     }
                               9245                 :                : #ifdef HAVE_INT128
  447                          9246         [ +  + ]:           2691 :     if (var2ndigits <= 4)
                               9247                 :                :     {
                               9248                 :                :         int64       idivisor;
                               9249                 :                :         int         idivisor_weight;
                               9250                 :                : 
                               9251                 :             21 :         idivisor = var2->digits[0];
                               9252                 :             21 :         idivisor_weight = var2->weight;
                               9253         [ +  + ]:             75 :         for (i = 1; i < var2ndigits; i++)
                               9254                 :                :         {
                               9255                 :             54 :             idivisor = idivisor * NBASE + var2->digits[i];
                               9256                 :             54 :             idivisor_weight--;
                               9257                 :                :         }
                               9258         [ -  + ]:             21 :         if (var2->sign == NUMERIC_NEG)
  447 dean.a.rasheed@gmail     9259                 :UBC           0 :             idivisor = -idivisor;
                               9260                 :                : 
  447 dean.a.rasheed@gmail     9261                 :CBC          21 :         div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
                               9262                 :             21 :         return;
                               9263                 :                :     }
                               9264                 :                : #endif
                               9265                 :                : 
                               9266                 :                :     /*
                               9267                 :                :      * Otherwise, perform full long division.
                               9268                 :                :      */
                               9269                 :                : 
                               9270                 :                :     /* Result zero check */
 7695 tgl@sss.pgh.pa.us        9271         [ +  + ]:           2670 :     if (var1ndigits == 0)
                               9272                 :                :     {
 8853                          9273                 :              6 :         zero_var(result);
 7695                          9274                 :              6 :         result->dscale = rscale;
 9237 JanWieck@Yahoo.com       9275                 :              6 :         return;
                               9276                 :                :     }
                               9277                 :                : 
                               9278                 :                :     /*
                               9279                 :                :      * Determine the result sign, weight and number of digits to calculate
                               9280                 :                :      */
 7695 tgl@sss.pgh.pa.us        9281         [ +  + ]:           2664 :     if (var1->sign == var2->sign)
                               9282                 :           2628 :         res_sign = NUMERIC_POS;
                               9283                 :                :     else
                               9284                 :             36 :         res_sign = NUMERIC_NEG;
                               9285                 :           2664 :     res_weight = var1->weight - var2->weight + 1;
                               9286                 :                :     /* The number of accurate result digits we need to produce: */
 7559 bruce@momjian.us         9287                 :           2664 :     div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               9288                 :                :     /* Add guard digits for roundoff error */
 7695 tgl@sss.pgh.pa.us        9289                 :           2664 :     div_ndigits += DIV_GUARD_DIGITS;
                               9290         [ -  + ]:           2664 :     if (div_ndigits < DIV_GUARD_DIGITS)
 7695 tgl@sss.pgh.pa.us        9291                 :UBC           0 :         div_ndigits = DIV_GUARD_DIGITS;
                               9292                 :                : 
                               9293                 :                :     /*
                               9294                 :                :      * We do the arithmetic in an array "div[]" of signed int's.  Since
                               9295                 :                :      * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
                               9296                 :                :      * to avoid normalizing carries immediately.
                               9297                 :                :      *
                               9298                 :                :      * We start with div[] containing one zero digit followed by the
                               9299                 :                :      * dividend's digits (plus appended zeroes to reach the desired precision
                               9300                 :                :      * including guard digits).  Each step of the main loop computes an
                               9301                 :                :      * (approximate) quotient digit and stores it into div[], removing one
                               9302                 :                :      * position of dividend space.  A final pass of carry propagation takes
                               9303                 :                :      * care of any mistaken quotient digits.
                               9304                 :                :      *
                               9305                 :                :      * Note that div[] doesn't necessarily contain all of the digits from the
                               9306                 :                :      * dividend --- the desired precision plus guard digits might be less than
                               9307                 :                :      * the dividend's precision.  This happens, for example, in the square
                               9308                 :                :      * root algorithm, where we typically divide a 2N-digit number by an
                               9309                 :                :      * N-digit number, and only require a result with N digits of precision.
                               9310                 :                :      */
 7695 tgl@sss.pgh.pa.us        9311                 :CBC        2664 :     div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
 1478 dean.a.rasheed@gmail     9312                 :           2664 :     load_ndigits = Min(div_ndigits, var1ndigits);
                               9313         [ +  + ]:          36354 :     for (i = 0; i < load_ndigits; i++)
 7559 bruce@momjian.us         9314                 :          33690 :         div[i + 1] = var1digits[i];
                               9315                 :                : 
                               9316                 :                :     /*
                               9317                 :                :      * We estimate each quotient digit using floating-point arithmetic, taking
                               9318                 :                :      * the first four digits of the (current) dividend and divisor.  This must
                               9319                 :                :      * be float to avoid overflow.  The quotient digits will generally be off
                               9320                 :                :      * by no more than one from the exact answer.
                               9321                 :                :      */
 7695 tgl@sss.pgh.pa.us        9322                 :           2664 :     fdivisor = (double) var2digits[0];
                               9323         [ +  + ]:          10656 :     for (i = 1; i < 4; i++)
                               9324                 :                :     {
                               9325                 :           7992 :         fdivisor *= NBASE;
                               9326         [ +  - ]:           7992 :         if (i < var2ndigits)
                               9327                 :           7992 :             fdivisor += (double) var2digits[i];
                               9328                 :                :     }
                               9329                 :           2664 :     fdivisorinverse = 1.0 / fdivisor;
                               9330                 :                : 
                               9331                 :                :     /*
                               9332                 :                :      * maxdiv tracks the maximum possible absolute value of any div[] entry;
                               9333                 :                :      * when this threatens to exceed INT_MAX, we take the time to propagate
                               9334                 :                :      * carries.  Furthermore, we need to ensure that overflow doesn't occur
                               9335                 :                :      * during the carry propagation passes either.  The carry values may have
                               9336                 :                :      * an absolute value as high as INT_MAX/NBASE + 1, so really we must
                               9337                 :                :      * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
                               9338                 :                :      *
                               9339                 :                :      * To avoid overflow in maxdiv itself, it represents the max absolute
                               9340                 :                :      * value divided by NBASE-1, ie, at the top of the loop it is known that
                               9341                 :                :      * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
                               9342                 :                :      *
                               9343                 :                :      * Actually, though, that holds good only for div[] entries after div[qi];
                               9344                 :                :      * the adjustment done at the bottom of the loop may cause div[qi + 1] to
                               9345                 :                :      * exceed the maxdiv limit, so that div[qi] in the next iteration is
                               9346                 :                :      * beyond the limit.  This does not cause problems, as explained below.
                               9347                 :                :      */
                               9348                 :           2664 :     maxdiv = 1;
                               9349                 :                : 
                               9350                 :                :     /*
                               9351                 :                :      * Outer loop computes next quotient digit, which will go into div[qi]
                               9352                 :                :      */
                               9353         [ +  + ]:          45144 :     for (qi = 0; qi < div_ndigits; qi++)
                               9354                 :                :     {
                               9355                 :                :         /* Approximate the current dividend value */
                               9356                 :          42480 :         fdividend = (double) div[qi];
                               9357         [ +  + ]:         169920 :         for (i = 1; i < 4; i++)
                               9358                 :                :         {
                               9359                 :         127440 :             fdividend *= NBASE;
 7559 bruce@momjian.us         9360         [ +  + ]:         127440 :             if (qi + i <= div_ndigits)
                               9361                 :         119448 :                 fdividend += (double) div[qi + i];
                               9362                 :                :         }
                               9363                 :                :         /* Compute the (approximate) quotient digit */
 7695 tgl@sss.pgh.pa.us        9364                 :          42480 :         fquotient = fdividend * fdivisorinverse;
                               9365         [ +  + ]:          42480 :         qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
 7559 bruce@momjian.us         9366                 :              3 :             (((int) fquotient) - 1);    /* truncate towards -infinity */
                               9367                 :                : 
 7695 tgl@sss.pgh.pa.us        9368         [ +  + ]:          42480 :         if (qdigit != 0)
                               9369                 :                :         {
                               9370                 :                :             /* Do we need to normalize now? */
  555 peter@eisentraut.org     9371                 :          37983 :             maxdiv += abs(qdigit);
 3071 tgl@sss.pgh.pa.us        9372         [ +  + ]:          37983 :             if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
                               9373                 :                :             {
                               9374                 :                :                 /*
                               9375                 :                :                  * Yes, do it.  Note that if var2ndigits is much smaller than
                               9376                 :                :                  * div_ndigits, we can save a significant amount of effort
                               9377                 :                :                  * here by noting that we only need to normalise those div[]
                               9378                 :                :                  * entries touched where prior iterations subtracted multiples
                               9379                 :                :                  * of the divisor.
                               9380                 :                :                  */
 7695                          9381                 :             48 :                 carry = 0;
 1478 dean.a.rasheed@gmail     9382         [ +  + ]:            948 :                 for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
                               9383                 :                :                 {
 7695 tgl@sss.pgh.pa.us        9384                 :            900 :                     newdig = div[i] + carry;
                               9385         [ +  - ]:            900 :                     if (newdig < 0)
                               9386                 :                :                     {
 7559 bruce@momjian.us         9387                 :            900 :                         carry = -((-newdig - 1) / NBASE) - 1;
                               9388                 :            900 :                         newdig -= carry * NBASE;
                               9389                 :                :                     }
 7695 tgl@sss.pgh.pa.us        9390         [ #  # ]:UBC           0 :                     else if (newdig >= NBASE)
                               9391                 :                :                     {
 7559 bruce@momjian.us         9392                 :              0 :                         carry = newdig / NBASE;
                               9393                 :              0 :                         newdig -= carry * NBASE;
                               9394                 :                :                     }
                               9395                 :                :                     else
 7695 tgl@sss.pgh.pa.us        9396                 :              0 :                         carry = 0;
 7695 tgl@sss.pgh.pa.us        9397                 :CBC         900 :                     div[i] = newdig;
                               9398                 :                :                 }
                               9399                 :             48 :                 newdig = div[qi] + carry;
                               9400                 :             48 :                 div[qi] = newdig;
                               9401                 :                : 
                               9402                 :                :                 /*
                               9403                 :                :                  * All the div[] digits except possibly div[qi] are now in the
                               9404                 :                :                  * range 0..NBASE-1.  We do not need to consider div[qi] in
                               9405                 :                :                  * the maxdiv value anymore, so we can reset maxdiv to 1.
                               9406                 :                :                  */
 3063                          9407                 :             48 :                 maxdiv = 1;
                               9408                 :                : 
                               9409                 :                :                 /*
                               9410                 :                :                  * Recompute the quotient digit since new info may have
                               9411                 :                :                  * propagated into the top four dividend digits
                               9412                 :                :                  */
 7695                          9413                 :             48 :                 fdividend = (double) div[qi];
                               9414         [ +  + ]:            192 :                 for (i = 1; i < 4; i++)
                               9415                 :                :                 {
                               9416                 :            144 :                     fdividend *= NBASE;
 7559 bruce@momjian.us         9417         [ +  - ]:            144 :                     if (qi + i <= div_ndigits)
                               9418                 :            144 :                         fdividend += (double) div[qi + i];
                               9419                 :                :                 }
                               9420                 :                :                 /* Compute the (approximate) quotient digit */
 7695 tgl@sss.pgh.pa.us        9421                 :             48 :                 fquotient = fdividend * fdivisorinverse;
                               9422         [ +  - ]:             48 :                 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
 6756 bruce@momjian.us         9423                 :UBC           0 :                     (((int) fquotient) - 1);    /* truncate towards -infinity */
  555 peter@eisentraut.org     9424                 :CBC          48 :                 maxdiv += abs(qdigit);
                               9425                 :                :             }
                               9426                 :                : 
                               9427                 :                :             /*
                               9428                 :                :              * Subtract off the appropriate multiple of the divisor.
                               9429                 :                :              *
                               9430                 :                :              * The digits beyond div[qi] cannot overflow, because we know they
                               9431                 :                :              * will fall within the maxdiv limit.  As for div[qi] itself, note
                               9432                 :                :              * that qdigit is approximately trunc(div[qi] / vardigits[0]),
                               9433                 :                :              * which would make the new value simply div[qi] mod vardigits[0].
                               9434                 :                :              * The lower-order terms in qdigit can change this result by not
                               9435                 :                :              * more than about twice INT_MAX/NBASE, so overflow is impossible.
                               9436                 :                :              *
                               9437                 :                :              * This inner loop is the performance bottleneck for division, so
                               9438                 :                :              * code it in the same way as the inner loop of mul_var() so that
                               9439                 :                :              * it can be auto-vectorized.  We cast qdigit to NumericDigit
                               9440                 :                :              * before multiplying to allow the compiler to generate more
                               9441                 :                :              * efficient code (using 16-bit multiplication), which is safe
                               9442                 :                :              * since we know that the quotient digit is off by at most one, so
                               9443                 :                :              * there is no overflow risk.
                               9444                 :                :              */
 7695 tgl@sss.pgh.pa.us        9445         [ +  - ]:          37983 :             if (qdigit != 0)
                               9446                 :                :             {
 7559 bruce@momjian.us         9447                 :          37983 :                 int         istop = Min(var2ndigits, div_ndigits - qi + 1);
  777 dean.a.rasheed@gmail     9448                 :          37983 :                 int        *div_qi = &div[qi];
                               9449                 :                : 
 7695 tgl@sss.pgh.pa.us        9450         [ +  + ]:         465018 :                 for (i = 0; i < istop; i++)
  777 dean.a.rasheed@gmail     9451                 :         427035 :                     div_qi[i] -= ((NumericDigit) qdigit) * var2digits[i];
                               9452                 :                :             }
                               9453                 :                :         }
                               9454                 :                : 
                               9455                 :                :         /*
                               9456                 :                :          * The dividend digit we are about to replace might still be nonzero.
                               9457                 :                :          * Fold it into the next digit position.
                               9458                 :                :          *
                               9459                 :                :          * There is no risk of overflow here, although proving that requires
                               9460                 :                :          * some care.  Much as with the argument for div[qi] not overflowing,
                               9461                 :                :          * if we consider the first two terms in the numerator and denominator
                               9462                 :                :          * of qdigit, we can see that the final value of div[qi + 1] will be
                               9463                 :                :          * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
                               9464                 :                :          * Accounting for the lower-order terms is a bit complicated but ends
                               9465                 :                :          * up adding not much more than INT_MAX/NBASE to the possible range.
                               9466                 :                :          * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
                               9467                 :                :          * in the next loop iteration, it can't be large enough to cause
                               9468                 :                :          * overflow in the carry propagation step (if any), either.
                               9469                 :                :          *
                               9470                 :                :          * But having said that: div[qi] can be more than INT_MAX/NBASE, as
                               9471                 :                :          * noted above, which means that the product div[qi] * NBASE *can*
                               9472                 :                :          * overflow.  When that happens, adding it to div[qi + 1] will always
                               9473                 :                :          * cause a canceling overflow so that the end result is correct.  We
                               9474                 :                :          * could avoid the intermediate overflow by doing the multiplication
                               9475                 :                :          * and addition in int64 arithmetic, but so far there appears no need.
                               9476                 :                :          */
 7559 bruce@momjian.us         9477                 :          42480 :         div[qi + 1] += div[qi] * NBASE;
                               9478                 :                : 
 7695 tgl@sss.pgh.pa.us        9479                 :          42480 :         div[qi] = qdigit;
                               9480                 :                :     }
                               9481                 :                : 
                               9482                 :                :     /*
                               9483                 :                :      * Approximate and store the last quotient digit (div[div_ndigits])
                               9484                 :                :      */
                               9485                 :           2664 :     fdividend = (double) div[qi];
                               9486         [ +  + ]:          10656 :     for (i = 1; i < 4; i++)
                               9487                 :           7992 :         fdividend *= NBASE;
                               9488                 :           2664 :     fquotient = fdividend * fdivisorinverse;
                               9489         [ +  - ]:           2664 :     qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
 7559 bruce@momjian.us         9490                 :UBC           0 :         (((int) fquotient) - 1);    /* truncate towards -infinity */
 7695 tgl@sss.pgh.pa.us        9491                 :CBC        2664 :     div[qi] = qdigit;
                               9492                 :                : 
                               9493                 :                :     /*
                               9494                 :                :      * Because the quotient digits might be off by one, some of them might be
                               9495                 :                :      * -1 or NBASE at this point.  The represented value is correct in a
                               9496                 :                :      * mathematical sense, but it doesn't look right.  We do a final carry
                               9497                 :                :      * propagation pass to normalize the digits, which we combine with storing
                               9498                 :                :      * the result digits into the output.  Note that this is still done at
                               9499                 :                :      * full precision w/guard digits.
                               9500                 :                :      */
 7559 bruce@momjian.us         9501                 :           2664 :     alloc_var(result, div_ndigits + 1);
 7695 tgl@sss.pgh.pa.us        9502                 :           2664 :     res_digits = result->digits;
                               9503                 :           2664 :     carry = 0;
                               9504         [ +  + ]:          47808 :     for (i = div_ndigits; i >= 0; i--)
                               9505                 :                :     {
                               9506                 :          45144 :         newdig = div[i] + carry;
                               9507         [ +  + ]:          45144 :         if (newdig < 0)
                               9508                 :                :         {
 7559 bruce@momjian.us         9509                 :              6 :             carry = -((-newdig - 1) / NBASE) - 1;
                               9510                 :              6 :             newdig -= carry * NBASE;
                               9511                 :                :         }
 7695 tgl@sss.pgh.pa.us        9512         [ +  + ]:          45138 :         else if (newdig >= NBASE)
                               9513                 :                :         {
 7559 bruce@momjian.us         9514                 :            174 :             carry = newdig / NBASE;
                               9515                 :            174 :             newdig -= carry * NBASE;
                               9516                 :                :         }
                               9517                 :                :         else
 7695 tgl@sss.pgh.pa.us        9518                 :          44964 :             carry = 0;
                               9519                 :          45144 :         res_digits[i] = newdig;
                               9520                 :                :     }
                               9521         [ -  + ]:           2664 :     Assert(carry == 0);
                               9522                 :                : 
                               9523                 :           2664 :     pfree(div);
                               9524                 :                : 
                               9525                 :                :     /*
                               9526                 :                :      * Finally, round the result to the requested precision.
                               9527                 :                :      */
                               9528                 :           2664 :     result->weight = res_weight;
                               9529                 :           2664 :     result->sign = res_sign;
                               9530                 :                : 
                               9531                 :                :     /* Round to target rscale (and set result->dscale) */
 6889 bruce@momjian.us         9532         [ +  + ]:           2664 :     if (round)
                               9533                 :            405 :         round_var(result, rscale);
                               9534                 :                :     else
                               9535                 :           2259 :         trunc_var(result, rscale);
                               9536                 :                : 
                               9537                 :                :     /* Strip leading and trailing zeroes */
 7695 tgl@sss.pgh.pa.us        9538                 :           2664 :     strip_var(result);
                               9539                 :                : }
                               9540                 :                : 
                               9541                 :                : 
                               9542                 :                : /*
                               9543                 :                :  * div_var_int() -
                               9544                 :                :  *
                               9545                 :                :  *  Divide a numeric variable by a 32-bit integer with the specified weight.
                               9546                 :                :  *  The quotient var / (ival * NBASE^ival_weight) is stored in result.
                               9547                 :                :  */
                               9548                 :                : static void
  777 dean.a.rasheed@gmail     9549                 :         112492 : div_var_int(const NumericVar *var, int ival, int ival_weight,
                               9550                 :                :             NumericVar *result, int rscale, bool round)
                               9551                 :                : {
                               9552                 :         112492 :     NumericDigit *var_digits = var->digits;
                               9553                 :         112492 :     int         var_ndigits = var->ndigits;
                               9554                 :                :     int         res_sign;
                               9555                 :                :     int         res_weight;
                               9556                 :                :     int         res_ndigits;
                               9557                 :                :     NumericDigit *res_buf;
                               9558                 :                :     NumericDigit *res_digits;
                               9559                 :                :     uint32      divisor;
                               9560                 :                :     int         i;
                               9561                 :                : 
                               9562                 :                :     /* Guard against division by zero */
                               9563         [ -  + ]:         112492 :     if (ival == 0)
  777 dean.a.rasheed@gmail     9564         [ #  # ]:UBC           0 :         ereport(ERROR,
                               9565                 :                :                 errcode(ERRCODE_DIVISION_BY_ZERO),
                               9566                 :                :                 errmsg("division by zero"));
                               9567                 :                : 
                               9568                 :                :     /* Result zero check */
  777 dean.a.rasheed@gmail     9569         [ +  + ]:CBC      112492 :     if (var_ndigits == 0)
                               9570                 :                :     {
                               9571                 :           1180 :         zero_var(result);
                               9572                 :           1180 :         result->dscale = rscale;
                               9573                 :           1180 :         return;
                               9574                 :                :     }
                               9575                 :                : 
                               9576                 :                :     /*
                               9577                 :                :      * Determine the result sign, weight and number of digits to calculate.
                               9578                 :                :      * The weight figured here is correct if the emitted quotient has no
                               9579                 :                :      * leading zero digits; otherwise strip_var() will fix things up.
                               9580                 :                :      */
                               9581         [ +  + ]:         111312 :     if (var->sign == NUMERIC_POS)
                               9582         [ +  + ]:         109899 :         res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
                               9583                 :                :     else
                               9584         [ +  + ]:           1413 :         res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
                               9585                 :         111312 :     res_weight = var->weight - ival_weight;
                               9586                 :                :     /* The number of accurate result digits we need to produce: */
                               9587                 :         111312 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               9588                 :                :     /* ... but always at least 1 */
                               9589                 :         111312 :     res_ndigits = Max(res_ndigits, 1);
                               9590                 :                :     /* If rounding needed, figure one more digit to ensure correct result */
                               9591         [ +  + ]:         111312 :     if (round)
                               9592                 :          83522 :         res_ndigits++;
                               9593                 :                : 
                               9594                 :         111312 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                               9595                 :         111312 :     res_buf[0] = 0;             /* spare digit for later rounding */
                               9596                 :         111312 :     res_digits = res_buf + 1;
                               9597                 :                : 
                               9598                 :                :     /*
                               9599                 :                :      * Now compute the quotient digits.  This is the short division algorithm
                               9600                 :                :      * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
                               9601                 :                :      * allow the divisor to exceed the internal base.
                               9602                 :                :      *
                               9603                 :                :      * In this algorithm, the carry from one digit to the next is at most
                               9604                 :                :      * divisor - 1.  Therefore, while processing the next digit, carry may
                               9605                 :                :      * become as large as divisor * NBASE - 1, and so it requires a 64-bit
                               9606                 :                :      * integer if this exceeds UINT_MAX.
                               9607                 :                :      */
  555 peter@eisentraut.org     9608                 :         111312 :     divisor = abs(ival);
                               9609                 :                : 
  777 dean.a.rasheed@gmail     9610         [ +  + ]:         111312 :     if (divisor <= UINT_MAX / NBASE)
                               9611                 :                :     {
                               9612                 :                :         /* carry cannot overflow 32 bits */
                               9613                 :         109280 :         uint32      carry = 0;
                               9614                 :                : 
                               9615         [ +  + ]:        1063241 :         for (i = 0; i < res_ndigits; i++)
                               9616                 :                :         {
                               9617         [ +  + ]:         953961 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9618                 :         953961 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9619                 :         953961 :             carry = carry % divisor;
                               9620                 :                :         }
                               9621                 :                :     }
                               9622                 :                :     else
                               9623                 :                :     {
                               9624                 :                :         /* carry may exceed 32 bits */
                               9625                 :           2032 :         uint64      carry = 0;
                               9626                 :                : 
                               9627         [ +  + ]:           6429 :         for (i = 0; i < res_ndigits; i++)
                               9628                 :                :         {
                               9629         [ +  + ]:           4397 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9630                 :           4397 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9631                 :           4397 :             carry = carry % divisor;
                               9632                 :                :         }
                               9633                 :                :     }
                               9634                 :                : 
                               9635                 :                :     /* Store the quotient in result */
                               9636         [ +  + ]:         111312 :     digitbuf_free(result->buf);
                               9637                 :         111312 :     result->ndigits = res_ndigits;
                               9638                 :         111312 :     result->buf = res_buf;
                               9639                 :         111312 :     result->digits = res_digits;
                               9640                 :         111312 :     result->weight = res_weight;
                               9641                 :         111312 :     result->sign = res_sign;
                               9642                 :                : 
                               9643                 :                :     /* Round or truncate to target rscale (and set result->dscale) */
                               9644         [ +  + ]:         111312 :     if (round)
                               9645                 :          83522 :         round_var(result, rscale);
                               9646                 :                :     else
                               9647                 :          27790 :         trunc_var(result, rscale);
                               9648                 :                : 
                               9649                 :                :     /* Strip leading/trailing zeroes */
                               9650                 :         111312 :     strip_var(result);
                               9651                 :                : }
                               9652                 :                : 
                               9653                 :                : 
                               9654                 :                : #ifdef HAVE_INT128
                               9655                 :                : /*
                               9656                 :                :  * div_var_int64() -
                               9657                 :                :  *
                               9658                 :                :  *  Divide a numeric variable by a 64-bit integer with the specified weight.
                               9659                 :                :  *  The quotient var / (ival * NBASE^ival_weight) is stored in result.
                               9660                 :                :  *
                               9661                 :                :  *  This duplicates the logic in div_var_int(), so any changes made there
                               9662                 :                :  *  should be made here too.
                               9663                 :                :  */
                               9664                 :                : static void
  447                          9665                 :            270 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
                               9666                 :                :               NumericVar *result, int rscale, bool round)
                               9667                 :                : {
                               9668                 :            270 :     NumericDigit *var_digits = var->digits;
                               9669                 :            270 :     int         var_ndigits = var->ndigits;
                               9670                 :                :     int         res_sign;
                               9671                 :                :     int         res_weight;
                               9672                 :                :     int         res_ndigits;
                               9673                 :                :     NumericDigit *res_buf;
                               9674                 :                :     NumericDigit *res_digits;
                               9675                 :                :     uint64      divisor;
                               9676                 :                :     int         i;
                               9677                 :                : 
                               9678                 :                :     /* Guard against division by zero */
                               9679         [ -  + ]:            270 :     if (ival == 0)
  447 dean.a.rasheed@gmail     9680         [ #  # ]:UBC           0 :         ereport(ERROR,
                               9681                 :                :                 errcode(ERRCODE_DIVISION_BY_ZERO),
                               9682                 :                :                 errmsg("division by zero"));
                               9683                 :                : 
                               9684                 :                :     /* Result zero check */
  447 dean.a.rasheed@gmail     9685         [ +  + ]:CBC         270 :     if (var_ndigits == 0)
                               9686                 :                :     {
                               9687                 :             48 :         zero_var(result);
                               9688                 :             48 :         result->dscale = rscale;
                               9689                 :             48 :         return;
                               9690                 :                :     }
                               9691                 :                : 
                               9692                 :                :     /*
                               9693                 :                :      * Determine the result sign, weight and number of digits to calculate.
                               9694                 :                :      * The weight figured here is correct if the emitted quotient has no
                               9695                 :                :      * leading zero digits; otherwise strip_var() will fix things up.
                               9696                 :                :      */
                               9697         [ +  + ]:            222 :     if (var->sign == NUMERIC_POS)
                               9698         [ +  + ]:            135 :         res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
                               9699                 :                :     else
                               9700         [ +  + ]:             87 :         res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
                               9701                 :            222 :     res_weight = var->weight - ival_weight;
                               9702                 :                :     /* The number of accurate result digits we need to produce: */
                               9703                 :            222 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               9704                 :                :     /* ... but always at least 1 */
                               9705                 :            222 :     res_ndigits = Max(res_ndigits, 1);
                               9706                 :                :     /* If rounding needed, figure one more digit to ensure correct result */
                               9707         [ +  - ]:            222 :     if (round)
                               9708                 :            222 :         res_ndigits++;
                               9709                 :                : 
                               9710                 :            222 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                               9711                 :            222 :     res_buf[0] = 0;             /* spare digit for later rounding */
                               9712                 :            222 :     res_digits = res_buf + 1;
                               9713                 :                : 
                               9714                 :                :     /*
                               9715                 :                :      * Now compute the quotient digits.  This is the short division algorithm
                               9716                 :                :      * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
                               9717                 :                :      * allow the divisor to exceed the internal base.
                               9718                 :                :      *
                               9719                 :                :      * In this algorithm, the carry from one digit to the next is at most
                               9720                 :                :      * divisor - 1.  Therefore, while processing the next digit, carry may
                               9721                 :                :      * become as large as divisor * NBASE - 1, and so it requires a 128-bit
                               9722                 :                :      * integer if this exceeds PG_UINT64_MAX.
                               9723                 :                :      */
                               9724                 :            222 :     divisor = i64abs(ival);
                               9725                 :                : 
                               9726         [ +  + ]:            222 :     if (divisor <= PG_UINT64_MAX / NBASE)
                               9727                 :                :     {
                               9728                 :                :         /* carry cannot overflow 64 bits */
                               9729                 :            174 :         uint64      carry = 0;
                               9730                 :                : 
                               9731         [ +  + ]:           1785 :         for (i = 0; i < res_ndigits; i++)
                               9732                 :                :         {
                               9733         [ +  + ]:           1611 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9734                 :           1611 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9735                 :           1611 :             carry = carry % divisor;
                               9736                 :                :         }
                               9737                 :                :     }
                               9738                 :                :     else
                               9739                 :                :     {
                               9740                 :                :         /* carry may exceed 64 bits */
                               9741                 :             48 :         uint128     carry = 0;
                               9742                 :                : 
                               9743         [ +  + ]:            516 :         for (i = 0; i < res_ndigits; i++)
                               9744                 :                :         {
                               9745         [ +  + ]:            468 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9746                 :            468 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9747                 :            468 :             carry = carry % divisor;
                               9748                 :                :         }
                               9749                 :                :     }
                               9750                 :                : 
                               9751                 :                :     /* Store the quotient in result */
                               9752         [ +  + ]:            222 :     digitbuf_free(result->buf);
                               9753                 :            222 :     result->ndigits = res_ndigits;
                               9754                 :            222 :     result->buf = res_buf;
                               9755                 :            222 :     result->digits = res_digits;
                               9756                 :            222 :     result->weight = res_weight;
                               9757                 :            222 :     result->sign = res_sign;
                               9758                 :                : 
                               9759                 :                :     /* Round or truncate to target rscale (and set result->dscale) */
                               9760         [ +  - ]:            222 :     if (round)
                               9761                 :            222 :         round_var(result, rscale);
                               9762                 :                :     else
  447 dean.a.rasheed@gmail     9763                 :UBC           0 :         trunc_var(result, rscale);
                               9764                 :                : 
                               9765                 :                :     /* Strip leading/trailing zeroes */
  447 dean.a.rasheed@gmail     9766                 :CBC         222 :     strip_var(result);
                               9767                 :                : }
                               9768                 :                : #endif
                               9769                 :                : 
                               9770                 :                : 
                               9771                 :                : /*
                               9772                 :                :  * Default scale selection for division
                               9773                 :                :  *
                               9774                 :                :  * Returns the appropriate result scale for the division result.
                               9775                 :                :  */
                               9776                 :                : static int
 2408 andres@anarazel.de       9777                 :          76632 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
                               9778                 :                : {
                               9779                 :                :     int         weight1,
                               9780                 :                :                 weight2,
                               9781                 :                :                 qweight,
                               9782                 :                :                 i;
                               9783                 :                :     NumericDigit firstdigit1,
                               9784                 :                :                 firstdigit2;
                               9785                 :                :     int         rscale;
                               9786                 :                : 
                               9787                 :                :     /*
                               9788                 :                :      * The result scale of a division isn't specified in any SQL standard. For
                               9789                 :                :      * PostgreSQL we select a result scale that will give at least
                               9790                 :                :      * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
                               9791                 :                :      * result no less accurate than float8; but use a scale not less than
                               9792                 :                :      * either input's display scale.
                               9793                 :                :      */
                               9794                 :                : 
                               9795                 :                :     /* Get the actual (normalized) weight and first digit of each input */
                               9796                 :                : 
 7865 tgl@sss.pgh.pa.us        9797                 :          76632 :     weight1 = 0;                /* values to use if var1 is zero */
                               9798                 :          76632 :     firstdigit1 = 0;
                               9799         [ +  + ]:          76632 :     for (i = 0; i < var1->ndigits; i++)
                               9800                 :                :     {
                               9801                 :          75737 :         firstdigit1 = var1->digits[i];
                               9802         [ +  - ]:          75737 :         if (firstdigit1 != 0)
                               9803                 :                :         {
                               9804                 :          75737 :             weight1 = var1->weight - i;
                               9805                 :          75737 :             break;
                               9806                 :                :         }
                               9807                 :                :     }
                               9808                 :                : 
                               9809                 :          76632 :     weight2 = 0;                /* values to use if var2 is zero */
                               9810                 :          76632 :     firstdigit2 = 0;
                               9811         [ +  + ]:          76632 :     for (i = 0; i < var2->ndigits; i++)
                               9812                 :                :     {
                               9813                 :          76607 :         firstdigit2 = var2->digits[i];
                               9814         [ +  - ]:          76607 :         if (firstdigit2 != 0)
                               9815                 :                :         {
                               9816                 :          76607 :             weight2 = var2->weight - i;
                               9817                 :          76607 :             break;
                               9818                 :                :         }
                               9819                 :                :     }
                               9820                 :                : 
                               9821                 :                :     /*
                               9822                 :                :      * Estimate weight of quotient.  If the two first digits are equal, we
                               9823                 :                :      * can't be sure, but assume that var1 is less than var2.
                               9824                 :                :      */
                               9825                 :          76632 :     qweight = weight1 - weight2;
                               9826         [ +  + ]:          76632 :     if (firstdigit1 <= firstdigit2)
                               9827                 :          67241 :         qweight--;
                               9828                 :                : 
                               9829                 :                :     /* Select result scale */
 7695                          9830                 :          76632 :     rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
                               9831                 :          76632 :     rscale = Max(rscale, var1->dscale);
                               9832                 :          76632 :     rscale = Max(rscale, var2->dscale);
                               9833                 :          76632 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               9834                 :          76632 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               9835                 :                : 
                               9836                 :          76632 :     return rscale;
                               9837                 :                : }
                               9838                 :                : 
                               9839                 :                : 
                               9840                 :                : /*
                               9841                 :                :  * mod_var() -
                               9842                 :                :  *
                               9843                 :                :  *  Calculate the modulo of two numerics at variable level
                               9844                 :                :  */
                               9845                 :                : static void
 2408 andres@anarazel.de       9846                 :          27265 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               9847                 :                : {
                               9848                 :                :     NumericVar  tmp;
                               9849                 :                : 
 9237 JanWieck@Yahoo.com       9850                 :          27265 :     init_var(&tmp);
                               9851                 :                : 
                               9852                 :                :     /* ---------
                               9853                 :                :      * We do this using the equation
                               9854                 :                :      *      mod(x,y) = x - trunc(x/y)*y
                               9855                 :                :      * div_var can be persuaded to give us trunc(x/y) directly.
                               9856                 :                :      * ----------
                               9857                 :                :      */
 5854 tgl@sss.pgh.pa.us        9858                 :          27265 :     div_var(var1, var2, &tmp, 0, false);
                               9859                 :                : 
                               9860                 :          27259 :     mul_var(var2, &tmp, &tmp, var2->dscale);
                               9861                 :                : 
 9237 JanWieck@Yahoo.com       9862                 :          27259 :     sub_var(var1, &tmp, result);
                               9863                 :                : 
                               9864                 :          27259 :     free_var(&tmp);
                               9865                 :          27259 : }
                               9866                 :                : 
                               9867                 :                : 
                               9868                 :                : /*
                               9869                 :                :  * div_mod_var() -
                               9870                 :                :  *
                               9871                 :                :  *  Calculate the truncated integer quotient and numeric remainder of two
                               9872                 :                :  *  numeric variables.  The remainder is precise to var2's dscale.
                               9873                 :                :  */
                               9874                 :                : static void
 1478 dean.a.rasheed@gmail     9875                 :           2259 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
                               9876                 :                :             NumericVar *quot, NumericVar *rem)
                               9877                 :                : {
                               9878                 :                :     NumericVar  q;
                               9879                 :                :     NumericVar  r;
                               9880                 :                : 
                               9881                 :           2259 :     init_var(&q);
                               9882                 :           2259 :     init_var(&r);
                               9883                 :                : 
                               9884                 :                :     /*
                               9885                 :                :      * Use div_var_fast() to get an initial estimate for the integer quotient.
                               9886                 :                :      * This might be inaccurate (per the warning in div_var_fast's comments),
                               9887                 :                :      * but we can correct it below.
                               9888                 :                :      */
                               9889                 :           2259 :     div_var_fast(var1, var2, &q, 0, false);
                               9890                 :                : 
                               9891                 :                :     /* Compute initial estimate of remainder using the quotient estimate. */
                               9892                 :           2259 :     mul_var(var2, &q, &r, var2->dscale);
                               9893                 :           2259 :     sub_var(var1, &r, &r);
                               9894                 :                : 
                               9895                 :                :     /*
                               9896                 :                :      * Adjust the results if necessary --- the remainder should have the same
                               9897                 :                :      * sign as var1, and its absolute value should be less than the absolute
                               9898                 :                :      * value of var2.
                               9899                 :                :      */
                               9900   [ +  -  -  + ]:           2259 :     while (r.ndigits != 0 && r.sign != var1->sign)
                               9901                 :                :     {
                               9902                 :                :         /* The absolute value of the quotient is too large */
 1478 dean.a.rasheed@gmail     9903         [ #  # ]:UBC           0 :         if (var1->sign == var2->sign)
                               9904                 :                :         {
                               9905                 :              0 :             sub_var(&q, &const_one, &q);
                               9906                 :              0 :             add_var(&r, var2, &r);
                               9907                 :                :         }
                               9908                 :                :         else
                               9909                 :                :         {
                               9910                 :              0 :             add_var(&q, &const_one, &q);
                               9911                 :              0 :             sub_var(&r, var2, &r);
                               9912                 :                :         }
                               9913                 :                :     }
                               9914                 :                : 
 1478 dean.a.rasheed@gmail     9915         [ -  + ]:CBC        2259 :     while (cmp_abs(&r, var2) >= 0)
                               9916                 :                :     {
                               9917                 :                :         /* The absolute value of the quotient is too small */
 1478 dean.a.rasheed@gmail     9918         [ #  # ]:UBC           0 :         if (var1->sign == var2->sign)
                               9919                 :                :         {
                               9920                 :              0 :             add_var(&q, &const_one, &q);
                               9921                 :              0 :             sub_var(&r, var2, &r);
                               9922                 :                :         }
                               9923                 :                :         else
                               9924                 :                :         {
                               9925                 :              0 :             sub_var(&q, &const_one, &q);
                               9926                 :              0 :             add_var(&r, var2, &r);
                               9927                 :                :         }
                               9928                 :                :     }
                               9929                 :                : 
 1478 dean.a.rasheed@gmail     9930                 :CBC        2259 :     set_var_from_var(&q, quot);
                               9931                 :           2259 :     set_var_from_var(&r, rem);
                               9932                 :                : 
                               9933                 :           2259 :     free_var(&q);
                               9934                 :           2259 :     free_var(&r);
                               9935                 :           2259 : }
                               9936                 :                : 
                               9937                 :                : 
                               9938                 :                : /*
                               9939                 :                :  * ceil_var() -
                               9940                 :                :  *
                               9941                 :                :  *  Return the smallest integer greater than or equal to the argument
                               9942                 :                :  *  on variable level
                               9943                 :                :  */
                               9944                 :                : static void
 2408 andres@anarazel.de       9945                 :            102 : ceil_var(const NumericVar *var, NumericVar *result)
                               9946                 :                : {
                               9947                 :                :     NumericVar  tmp;
                               9948                 :                : 
 9237 JanWieck@Yahoo.com       9949                 :            102 :     init_var(&tmp);
                               9950                 :            102 :     set_var_from_var(var, &tmp);
                               9951                 :                : 
 7695 tgl@sss.pgh.pa.us        9952                 :            102 :     trunc_var(&tmp, 0);
                               9953                 :                : 
                               9954   [ +  +  +  + ]:            102 :     if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
 9237 JanWieck@Yahoo.com       9955                 :             30 :         add_var(&tmp, &const_one, &tmp);
                               9956                 :                : 
                               9957                 :            102 :     set_var_from_var(&tmp, result);
                               9958                 :            102 :     free_var(&tmp);
                               9959                 :            102 : }
                               9960                 :                : 
                               9961                 :                : 
                               9962                 :                : /*
                               9963                 :                :  * floor_var() -
                               9964                 :                :  *
                               9965                 :                :  *  Return the largest integer equal to or less than the argument
                               9966                 :                :  *  on variable level
                               9967                 :                :  */
                               9968                 :                : static void
 2408 andres@anarazel.de       9969                 :            288 : floor_var(const NumericVar *var, NumericVar *result)
                               9970                 :                : {
                               9971                 :                :     NumericVar  tmp;
                               9972                 :                : 
 9237 JanWieck@Yahoo.com       9973                 :            288 :     init_var(&tmp);
                               9974                 :            288 :     set_var_from_var(var, &tmp);
                               9975                 :                : 
 7695 tgl@sss.pgh.pa.us        9976                 :            288 :     trunc_var(&tmp, 0);
                               9977                 :                : 
                               9978   [ +  +  +  + ]:            288 :     if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
 9237 JanWieck@Yahoo.com       9979                 :             15 :         sub_var(&tmp, &const_one, &tmp);
                               9980                 :                : 
                               9981                 :            288 :     set_var_from_var(&tmp, result);
                               9982                 :            288 :     free_var(&tmp);
                               9983                 :            288 : }
                               9984                 :                : 
                               9985                 :                : 
                               9986                 :                : /*
                               9987                 :                :  * gcd_var() -
                               9988                 :                :  *
                               9989                 :                :  *  Calculate the greatest common divisor of two numerics at variable level
                               9990                 :                :  */
                               9991                 :                : static void
 1541 dean.a.rasheed@gmail     9992                 :            111 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               9993                 :                : {
                               9994                 :                :     int         res_dscale;
                               9995                 :                :     int         cmp;
                               9996                 :                :     NumericVar  tmp_arg;
                               9997                 :                :     NumericVar  mod;
                               9998                 :                : 
                               9999                 :            111 :     res_dscale = Max(var1->dscale, var2->dscale);
                              10000                 :                : 
                              10001                 :                :     /*
                              10002                 :                :      * Arrange for var1 to be the number with the greater absolute value.
                              10003                 :                :      *
                              10004                 :                :      * This would happen automatically in the loop below, but avoids an
                              10005                 :                :      * expensive modulo operation.
                              10006                 :                :      */
                              10007                 :            111 :     cmp = cmp_abs(var1, var2);
                              10008         [ +  + ]:            111 :     if (cmp < 0)
                              10009                 :                :     {
                              10010                 :             42 :         const NumericVar *tmp = var1;
                              10011                 :                : 
                              10012                 :             42 :         var1 = var2;
                              10013                 :             42 :         var2 = tmp;
                              10014                 :                :     }
                              10015                 :                : 
                              10016                 :                :     /*
                              10017                 :                :      * Also avoid the taking the modulo if the inputs have the same absolute
                              10018                 :                :      * value, or if the smaller input is zero.
                              10019                 :                :      */
                              10020   [ +  +  +  + ]:            111 :     if (cmp == 0 || var2->ndigits == 0)
                              10021                 :                :     {
                              10022                 :             36 :         set_var_from_var(var1, result);
                              10023                 :             36 :         result->sign = NUMERIC_POS;
                              10024                 :             36 :         result->dscale = res_dscale;
                              10025                 :             36 :         return;
                              10026                 :                :     }
                              10027                 :                : 
                              10028                 :             75 :     init_var(&tmp_arg);
                              10029                 :             75 :     init_var(&mod);
                              10030                 :                : 
                              10031                 :                :     /* Use the Euclidean algorithm to find the GCD */
                              10032                 :             75 :     set_var_from_var(var1, &tmp_arg);
                              10033                 :             75 :     set_var_from_var(var2, result);
                              10034                 :                : 
                              10035                 :                :     for (;;)
                              10036                 :                :     {
                              10037                 :                :         /* this loop can take a while, so allow it to be interrupted */
                              10038         [ -  + ]:            294 :         CHECK_FOR_INTERRUPTS();
                              10039                 :                : 
                              10040                 :            294 :         mod_var(&tmp_arg, result, &mod);
                              10041         [ +  + ]:            294 :         if (mod.ndigits == 0)
                              10042                 :             75 :             break;
                              10043                 :            219 :         set_var_from_var(result, &tmp_arg);
                              10044                 :            219 :         set_var_from_var(&mod, result);
                              10045                 :                :     }
                              10046                 :             75 :     result->sign = NUMERIC_POS;
                              10047                 :             75 :     result->dscale = res_dscale;
                              10048                 :                : 
                              10049                 :             75 :     free_var(&tmp_arg);
                              10050                 :             75 :     free_var(&mod);
                              10051                 :                : }
                              10052                 :                : 
                              10053                 :                : 
                              10054                 :                : /*
                              10055                 :                :  * sqrt_var() -
                              10056                 :                :  *
                              10057                 :                :  *  Compute the square root of x using the Karatsuba Square Root algorithm.
                              10058                 :                :  *  NOTE: we allow rscale < 0 here, implying rounding before the decimal
                              10059                 :                :  *  point.
                              10060                 :                :  */
                              10061                 :                : static void
 2408 andres@anarazel.de      10062                 :           2097 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
                              10063                 :                : {
                              10064                 :                :     int         stat;
                              10065                 :                :     int         res_weight;
                              10066                 :                :     int         res_ndigits;
                              10067                 :                :     int         src_ndigits;
                              10068                 :                :     int         step;
                              10069                 :                :     int         ndigits[32];
                              10070                 :                :     int         blen;
                              10071                 :                :     int64       arg_int64;
                              10072                 :                :     int         src_idx;
                              10073                 :                :     int64       s_int64;
                              10074                 :                :     int64       r_int64;
                              10075                 :                :     NumericVar  s_var;
                              10076                 :                :     NumericVar  r_var;
                              10077                 :                :     NumericVar  a0_var;
                              10078                 :                :     NumericVar  a1_var;
                              10079                 :                :     NumericVar  q_var;
                              10080                 :                :     NumericVar  u_var;
                              10081                 :                : 
 9237 JanWieck@Yahoo.com      10082                 :           2097 :     stat = cmp_var(arg, &const_zero);
                              10083         [ +  + ]:           2097 :     if (stat == 0)
                              10084                 :                :     {
 7695 tgl@sss.pgh.pa.us       10085                 :              9 :         zero_var(result);
                              10086                 :              9 :         result->dscale = rscale;
 9237 JanWieck@Yahoo.com      10087                 :              9 :         return;
                              10088                 :                :     }
                              10089                 :                : 
                              10090                 :                :     /*
                              10091                 :                :      * SQL2003 defines sqrt() in terms of power, so we need to emit the right
                              10092                 :                :      * SQLSTATE error code if the operand is negative.
                              10093                 :                :      */
                              10094         [ +  + ]:           2088 :     if (stat < 0)
 7567 tgl@sss.pgh.pa.us       10095         [ +  - ]:              3 :         ereport(ERROR,
                              10096                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                              10097                 :                :                  errmsg("cannot take square root of a negative number")));
                              10098                 :                : 
 1478 dean.a.rasheed@gmail    10099                 :           2085 :     init_var(&s_var);
                              10100                 :           2085 :     init_var(&r_var);
                              10101                 :           2085 :     init_var(&a0_var);
                              10102                 :           2085 :     init_var(&a1_var);
                              10103                 :           2085 :     init_var(&q_var);
                              10104                 :           2085 :     init_var(&u_var);
                              10105                 :                : 
                              10106                 :                :     /*
                              10107                 :                :      * The result weight is half the input weight, rounded towards minus
                              10108                 :                :      * infinity --- res_weight = floor(arg->weight / 2).
                              10109                 :                :      */
                              10110         [ +  + ]:           2085 :     if (arg->weight >= 0)
                              10111                 :           1929 :         res_weight = arg->weight / 2;
                              10112                 :                :     else
                              10113                 :            156 :         res_weight = -((-arg->weight - 1) / 2 + 1);
                              10114                 :                : 
                              10115                 :                :     /*
                              10116                 :                :      * Number of NBASE digits to compute.  To ensure correct rounding, compute
                              10117                 :                :      * at least 1 extra decimal digit.  We explicitly allow rscale to be
                              10118                 :                :      * negative here, but must always compute at least 1 NBASE digit.  Thus
                              10119                 :                :      * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
                              10120                 :                :      */
                              10121         [ +  - ]:           2085 :     if (rscale + 1 >= 0)
                              10122                 :           2085 :         res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
                              10123                 :                :     else
 1478 dean.a.rasheed@gmail    10124                 :UBC           0 :         res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
 1478 dean.a.rasheed@gmail    10125                 :CBC        2085 :     res_ndigits = Max(res_ndigits, 1);
                              10126                 :                : 
                              10127                 :                :     /*
                              10128                 :                :      * Number of source NBASE digits logically required to produce a result
                              10129                 :                :      * with this precision --- every digit before the decimal point, plus 2
                              10130                 :                :      * for each result digit after the decimal point (or minus 2 for each
                              10131                 :                :      * result digit we round before the decimal point).
                              10132                 :                :      */
                              10133                 :           2085 :     src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
                              10134                 :           2085 :     src_ndigits = Max(src_ndigits, 1);
                              10135                 :                : 
                              10136                 :                :     /* ----------
                              10137                 :                :      * From this point on, we treat the input and the result as integers and
                              10138                 :                :      * compute the integer square root and remainder using the Karatsuba
                              10139                 :                :      * Square Root algorithm, which may be written recursively as follows:
                              10140                 :                :      *
                              10141                 :                :      *  SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
                              10142                 :                :      *      [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
                              10143                 :                :      *        0 <= a0,a1,a2 < b and a3 >= b/4 ]
                              10144                 :                :      *      Let (s,r) = SqrtRem(a3*b + a2)
                              10145                 :                :      *      Let (q,u) = DivRem(r*b + a1, 2*s)
                              10146                 :                :      *      Let s = s*b + q
                              10147                 :                :      *      Let r = u*b + a0 - q^2
                              10148                 :                :      *      If r < 0 Then
                              10149                 :                :      *          Let r = r + s
                              10150                 :                :      *          Let s = s - 1
                              10151                 :                :      *          Let r = r + s
                              10152                 :                :      *      Return (s,r)
                              10153                 :                :      *
                              10154                 :                :      * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
                              10155                 :                :      * RR-3805, November 1999.  At the time of writing this was available
                              10156                 :                :      * on the net at <https://hal.inria.fr/inria-00072854>.
                              10157                 :                :      *
                              10158                 :                :      * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
                              10159                 :                :      * "choose a base b such that n requires at least four base-b digits to
                              10160                 :                :      * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
                              10161                 :                :      * than b".  For optimal performance, b should have approximately a
                              10162                 :                :      * quarter the number of digits in the input, so that the outer square
                              10163                 :                :      * root computes roughly twice as many digits as the inner one.  For
                              10164                 :                :      * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
                              10165                 :                :      *
                              10166                 :                :      * We implement the algorithm iteratively rather than recursively, to
                              10167                 :                :      * allow the working variables to be reused.  With this approach, each
                              10168                 :                :      * digit of the input is read precisely once --- src_idx tracks the number
                              10169                 :                :      * of input digits used so far.
                              10170                 :                :      *
                              10171                 :                :      * The array ndigits[] holds the number of NBASE digits of the input that
                              10172                 :                :      * will have been used at the end of each iteration, which roughly doubles
                              10173                 :                :      * each time.  Note that the array elements are stored in reverse order,
                              10174                 :                :      * so if the final iteration requires src_ndigits = 37 input digits, the
                              10175                 :                :      * array will contain [37,19,11,7,5,3], and we would start by computing
                              10176                 :                :      * the square root of the 3 most significant NBASE digits.
                              10177                 :                :      *
                              10178                 :                :      * In each iteration, we choose blen to be the largest integer for which
                              10179                 :                :      * the input number has a3 >= b/4, when written in the form above.  In
                              10180                 :                :      * general, this means blen = src_ndigits / 4 (truncated), but if
                              10181                 :                :      * src_ndigits is a multiple of 4, that might lead to the coefficient a3
                              10182                 :                :      * being less than b/4 (if the first input digit is less than NBASE/4), in
                              10183                 :                :      * which case we choose blen = src_ndigits / 4 - 1.  The number of digits
                              10184                 :                :      * in the inner square root is then src_ndigits - 2*blen.  So, for
                              10185                 :                :      * example, if we have src_ndigits = 26 initially, the array ndigits[]
                              10186                 :                :      * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
                              10187                 :                :      * the first input digit.
                              10188                 :                :      *
                              10189                 :                :      * Additionally, we can put an upper bound on the number of steps required
                              10190                 :                :      * as follows --- suppose that the number of source digits is an n-bit
                              10191                 :                :      * number in the range [2^(n-1), 2^n-1], then blen will be in the range
                              10192                 :                :      * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
                              10193                 :                :      * root will be in the range [2^(n-2), 2^(n-1)+1].  In the next step, blen
                              10194                 :                :      * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
                              10195                 :                :      * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
                              10196                 :                :      * This pattern repeats, and in the worst case the array ndigits[] will
                              10197                 :                :      * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
                              10198                 :                :      * will require n steps.  Therefore, since all digit array sizes are
                              10199                 :                :      * signed 32-bit integers, the number of steps required is guaranteed to
                              10200                 :                :      * be less than 32.
                              10201                 :                :      * ----------
                              10202                 :                :      */
                              10203                 :           2085 :     step = 0;
                              10204         [ +  + ]:           9981 :     while ((ndigits[step] = src_ndigits) > 4)
                              10205                 :                :     {
                              10206                 :                :         /* Choose b so that a3 >= b/4, as described above */
                              10207                 :           7896 :         blen = src_ndigits / 4;
                              10208   [ +  +  +  + ]:           7896 :         if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
                              10209                 :            162 :             blen--;
                              10210                 :                : 
                              10211                 :                :         /* Number of digits in the next step (inner square root) */
                              10212                 :           7896 :         src_ndigits -= 2 * blen;
                              10213                 :           7896 :         step++;
                              10214                 :                :     }
                              10215                 :                : 
                              10216                 :                :     /*
                              10217                 :                :      * First iteration (innermost square root and remainder):
                              10218                 :                :      *
                              10219                 :                :      * Here src_ndigits <= 4, and the input fits in an int64.  Its square root
                              10220                 :                :      * has at most 9 decimal digits, so estimate it using double precision
                              10221                 :                :      * arithmetic, which will in fact almost certainly return the correct
                              10222                 :                :      * result with no further correction required.
                              10223                 :                :      */
                              10224                 :           2085 :     arg_int64 = arg->digits[0];
                              10225         [ +  + ]:           6657 :     for (src_idx = 1; src_idx < src_ndigits; src_idx++)
                              10226                 :                :     {
                              10227                 :           4572 :         arg_int64 *= NBASE;
                              10228         [ +  + ]:           4572 :         if (src_idx < arg->ndigits)
                              10229                 :           3843 :             arg_int64 += arg->digits[src_idx];
                              10230                 :                :     }
                              10231                 :                : 
                              10232                 :           2085 :     s_int64 = (int64) sqrt((double) arg_int64);
                              10233                 :           2085 :     r_int64 = arg_int64 - s_int64 * s_int64;
                              10234                 :                : 
                              10235                 :                :     /*
                              10236                 :                :      * Use Newton's method to correct the result, if necessary.
                              10237                 :                :      *
                              10238                 :                :      * This uses integer division with truncation to compute the truncated
                              10239                 :                :      * integer square root by iterating using the formula x -> (x + n/x) / 2.
                              10240                 :                :      * This is known to converge to isqrt(n), unless n+1 is a perfect square.
                              10241                 :                :      * If n+1 is a perfect square, the sequence will oscillate between the two
                              10242                 :                :      * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
                              10243                 :                :      * checking the remainder.
                              10244                 :                :      */
                              10245   [ -  +  -  + ]:           2085 :     while (r_int64 < 0 || r_int64 > 2 * s_int64)
                              10246                 :                :     {
 1478 dean.a.rasheed@gmail    10247                 :UBC           0 :         s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
                              10248                 :              0 :         r_int64 = arg_int64 - s_int64 * s_int64;
                              10249                 :                :     }
                              10250                 :                : 
                              10251                 :                :     /*
                              10252                 :                :      * Iterations with src_ndigits <= 8:
                              10253                 :                :      *
                              10254                 :                :      * The next 1 or 2 iterations compute larger (outer) square roots with
                              10255                 :                :      * src_ndigits <= 8, so the result still fits in an int64 (even though the
                              10256                 :                :      * input no longer does) and we can continue to compute using int64
                              10257                 :                :      * variables to avoid more expensive numeric computations.
                              10258                 :                :      *
                              10259                 :                :      * It is fairly easy to see that there is no risk of the intermediate
                              10260                 :                :      * values below overflowing 64-bit integers.  In the worst case, the
                              10261                 :                :      * previous iteration will have computed a 3-digit square root (of a
                              10262                 :                :      * 6-digit input less than NBASE^6 / 4), so at the start of this
                              10263                 :                :      * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
                              10264                 :                :      * less than 10^12.  In this case, blen will be 1, so numer will be less
                              10265                 :                :      * than 10^17, and denom will be less than 10^12 (and hence u will also be
                              10266                 :                :      * less than 10^12).  Finally, since q^2 = u*b + a0 - r, we can also be
                              10267                 :                :      * sure that q^2 < 10^17.  Therefore all these quantities fit comfortably
                              10268                 :                :      * in 64-bit integers.
                              10269                 :                :      */
 1478 dean.a.rasheed@gmail    10270                 :CBC        2085 :     step--;
                              10271   [ +  -  +  + ]:           5283 :     while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
                              10272                 :                :     {
                              10273                 :                :         int         b;
                              10274                 :                :         int         a0;
                              10275                 :                :         int         a1;
                              10276                 :                :         int         i;
                              10277                 :                :         int64       numer;
                              10278                 :                :         int64       denom;
                              10279                 :                :         int64       q;
                              10280                 :                :         int64       u;
                              10281                 :                : 
                              10282                 :           3198 :         blen = (src_ndigits - src_idx) / 2;
                              10283                 :                : 
                              10284                 :                :         /* Extract a1 and a0, and compute b */
                              10285                 :           3198 :         a0 = 0;
                              10286                 :           3198 :         a1 = 0;
                              10287                 :           3198 :         b = 1;
                              10288                 :                : 
                              10289         [ +  + ]:           6468 :         for (i = 0; i < blen; i++, src_idx++)
                              10290                 :                :         {
                              10291                 :           3270 :             b *= NBASE;
                              10292                 :           3270 :             a1 *= NBASE;
                              10293         [ +  + ]:           3270 :             if (src_idx < arg->ndigits)
                              10294                 :           2400 :                 a1 += arg->digits[src_idx];
                              10295                 :                :         }
                              10296                 :                : 
                              10297         [ +  + ]:           6468 :         for (i = 0; i < blen; i++, src_idx++)
                              10298                 :                :         {
                              10299                 :           3270 :             a0 *= NBASE;
                              10300         [ +  + ]:           3270 :             if (src_idx < arg->ndigits)
                              10301                 :           2322 :                 a0 += arg->digits[src_idx];
                              10302                 :                :         }
                              10303                 :                : 
                              10304                 :                :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
                              10305                 :           3198 :         numer = r_int64 * b + a1;
                              10306                 :           3198 :         denom = 2 * s_int64;
                              10307                 :           3198 :         q = numer / denom;
                              10308                 :           3198 :         u = numer - q * denom;
                              10309                 :                : 
                              10310                 :                :         /* Compute s = s*b + q and r = u*b + a0 - q^2 */
                              10311                 :           3198 :         s_int64 = s_int64 * b + q;
                              10312                 :           3198 :         r_int64 = u * b + a0 - q * q;
                              10313                 :                : 
                              10314         [ +  + ]:           3198 :         if (r_int64 < 0)
                              10315                 :                :         {
                              10316                 :                :             /* s is too large by 1; set r += s, s--, r += s */
                              10317                 :            105 :             r_int64 += s_int64;
                              10318                 :            105 :             s_int64--;
                              10319                 :            105 :             r_int64 += s_int64;
                              10320                 :                :         }
                              10321                 :                : 
                              10322         [ -  + ]:           3198 :         Assert(src_idx == src_ndigits); /* All input digits consumed */
                              10323                 :           3198 :         step--;
                              10324                 :                :     }
                              10325                 :                : 
                              10326                 :                :     /*
                              10327                 :                :      * On platforms with 128-bit integer support, we can further delay the
                              10328                 :                :      * need to use numeric variables.
                              10329                 :                :      */
                              10330                 :                : #ifdef HAVE_INT128
                              10331         [ +  - ]:           2085 :     if (step >= 0)
                              10332                 :                :     {
                              10333                 :                :         int128      s_int128;
                              10334                 :                :         int128      r_int128;
                              10335                 :                : 
                              10336                 :           2085 :         s_int128 = s_int64;
                              10337                 :           2085 :         r_int128 = r_int64;
                              10338                 :                : 
                              10339                 :                :         /*
                              10340                 :                :          * Iterations with src_ndigits <= 16:
                              10341                 :                :          *
                              10342                 :                :          * The result fits in an int128 (even though the input doesn't) so we
                              10343                 :                :          * use int128 variables to avoid more expensive numeric computations.
                              10344                 :                :          */
                              10345   [ +  +  +  + ]:           4524 :         while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
                              10346                 :                :         {
                              10347                 :                :             int64       b;
                              10348                 :                :             int64       a0;
                              10349                 :                :             int64       a1;
                              10350                 :                :             int64       i;
                              10351                 :                :             int128      numer;
                              10352                 :                :             int128      denom;
                              10353                 :                :             int128      q;
                              10354                 :                :             int128      u;
                              10355                 :                : 
                              10356                 :           2439 :             blen = (src_ndigits - src_idx) / 2;
                              10357                 :                : 
                              10358                 :                :             /* Extract a1 and a0, and compute b */
                              10359                 :           2439 :             a0 = 0;
                              10360                 :           2439 :             a1 = 0;
                              10361                 :           2439 :             b = 1;
                              10362                 :                : 
                              10363         [ +  + ]:           8040 :             for (i = 0; i < blen; i++, src_idx++)
                              10364                 :                :             {
                              10365                 :           5601 :                 b *= NBASE;
                              10366                 :           5601 :                 a1 *= NBASE;
                              10367         [ +  + ]:           5601 :                 if (src_idx < arg->ndigits)
                              10368                 :           3303 :                     a1 += arg->digits[src_idx];
                              10369                 :                :             }
                              10370                 :                : 
                              10371         [ +  + ]:           8040 :             for (i = 0; i < blen; i++, src_idx++)
                              10372                 :                :             {
                              10373                 :           5601 :                 a0 *= NBASE;
                              10374         [ +  + ]:           5601 :                 if (src_idx < arg->ndigits)
                              10375                 :           2235 :                     a0 += arg->digits[src_idx];
                              10376                 :                :             }
                              10377                 :                : 
                              10378                 :                :             /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
                              10379                 :           2439 :             numer = r_int128 * b + a1;
                              10380                 :           2439 :             denom = 2 * s_int128;
                              10381                 :           2439 :             q = numer / denom;
                              10382                 :           2439 :             u = numer - q * denom;
                              10383                 :                : 
                              10384                 :                :             /* Compute s = s*b + q and r = u*b + a0 - q^2 */
                              10385                 :           2439 :             s_int128 = s_int128 * b + q;
                              10386                 :           2439 :             r_int128 = u * b + a0 - q * q;
                              10387                 :                : 
                              10388         [ +  + ]:           2439 :             if (r_int128 < 0)
                              10389                 :                :             {
                              10390                 :                :                 /* s is too large by 1; set r += s, s--, r += s */
                              10391                 :             96 :                 r_int128 += s_int128;
                              10392                 :             96 :                 s_int128--;
                              10393                 :             96 :                 r_int128 += s_int128;
                              10394                 :                :             }
                              10395                 :                : 
                              10396         [ -  + ]:           2439 :             Assert(src_idx == src_ndigits); /* All input digits consumed */
                              10397                 :           2439 :             step--;
                              10398                 :                :         }
                              10399                 :                : 
                              10400                 :                :         /*
                              10401                 :                :          * All remaining iterations require numeric variables.  Convert the
                              10402                 :                :          * integer values to NumericVar and continue.  Note that in the final
                              10403                 :                :          * iteration we don't need the remainder, so we can save a few cycles
                              10404                 :                :          * there by not fully computing it.
                              10405                 :                :          */
                              10406                 :           2085 :         int128_to_numericvar(s_int128, &s_var);
                              10407         [ +  + ]:           2085 :         if (step >= 0)
                              10408                 :           1362 :             int128_to_numericvar(r_int128, &r_var);
                              10409                 :                :     }
                              10410                 :                :     else
                              10411                 :                :     {
 1478 dean.a.rasheed@gmail    10412                 :UBC           0 :         int64_to_numericvar(s_int64, &s_var);
                              10413                 :                :         /* step < 0, so we certainly don't need r */
                              10414                 :                :     }
                              10415                 :                : #else                           /* !HAVE_INT128 */
                              10416                 :                :     int64_to_numericvar(s_int64, &s_var);
                              10417                 :                :     if (step >= 0)
                              10418                 :                :         int64_to_numericvar(r_int64, &r_var);
                              10419                 :                : #endif                          /* HAVE_INT128 */
                              10420                 :                : 
                              10421                 :                :     /*
                              10422                 :                :      * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
                              10423                 :                :      * use numeric variables.
                              10424                 :                :      */
 1478 dean.a.rasheed@gmail    10425         [ +  + ]:CBC        4344 :     while (step >= 0)
                              10426                 :                :     {
                              10427                 :                :         int         tmp_len;
                              10428                 :                : 
                              10429                 :           2259 :         src_ndigits = ndigits[step];
                              10430                 :           2259 :         blen = (src_ndigits - src_idx) / 2;
                              10431                 :                : 
                              10432                 :                :         /* Extract a1 and a0 */
                              10433         [ +  + ]:           2259 :         if (src_idx < arg->ndigits)
                              10434                 :                :         {
                              10435                 :            756 :             tmp_len = Min(blen, arg->ndigits - src_idx);
                              10436                 :            756 :             alloc_var(&a1_var, tmp_len);
                              10437                 :            756 :             memcpy(a1_var.digits, arg->digits + src_idx,
                              10438                 :                :                    tmp_len * sizeof(NumericDigit));
                              10439                 :            756 :             a1_var.weight = blen - 1;
                              10440                 :            756 :             a1_var.sign = NUMERIC_POS;
                              10441                 :            756 :             a1_var.dscale = 0;
                              10442                 :            756 :             strip_var(&a1_var);
                              10443                 :                :         }
                              10444                 :                :         else
                              10445                 :                :         {
                              10446                 :           1503 :             zero_var(&a1_var);
                              10447                 :           1503 :             a1_var.dscale = 0;
                              10448                 :                :         }
                              10449                 :           2259 :         src_idx += blen;
                              10450                 :                : 
                              10451         [ +  + ]:           2259 :         if (src_idx < arg->ndigits)
                              10452                 :                :         {
                              10453                 :            756 :             tmp_len = Min(blen, arg->ndigits - src_idx);
                              10454                 :            756 :             alloc_var(&a0_var, tmp_len);
                              10455                 :            756 :             memcpy(a0_var.digits, arg->digits + src_idx,
                              10456                 :                :                    tmp_len * sizeof(NumericDigit));
                              10457                 :            756 :             a0_var.weight = blen - 1;
                              10458                 :            756 :             a0_var.sign = NUMERIC_POS;
                              10459                 :            756 :             a0_var.dscale = 0;
                              10460                 :            756 :             strip_var(&a0_var);
                              10461                 :                :         }
                              10462                 :                :         else
                              10463                 :                :         {
                              10464                 :           1503 :             zero_var(&a0_var);
                              10465                 :           1503 :             a0_var.dscale = 0;
                              10466                 :                :         }
                              10467                 :           2259 :         src_idx += blen;
                              10468                 :                : 
                              10469                 :                :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
                              10470                 :           2259 :         set_var_from_var(&r_var, &q_var);
                              10471                 :           2259 :         q_var.weight += blen;
                              10472                 :           2259 :         add_var(&q_var, &a1_var, &q_var);
                              10473                 :           2259 :         add_var(&s_var, &s_var, &u_var);
                              10474                 :           2259 :         div_mod_var(&q_var, &u_var, &q_var, &u_var);
                              10475                 :                : 
                              10476                 :                :         /* Compute s = s*b + q */
                              10477                 :           2259 :         s_var.weight += blen;
                              10478                 :           2259 :         add_var(&s_var, &q_var, &s_var);
                              10479                 :                : 
                              10480                 :                :         /*
                              10481                 :                :          * Compute r = u*b + a0 - q^2.
                              10482                 :                :          *
                              10483                 :                :          * In the final iteration, we don't actually need r; we just need to
                              10484                 :                :          * know whether it is negative, so that we know whether to adjust s.
                              10485                 :                :          * So instead of the final subtraction we can just compare.
                              10486                 :                :          */
                              10487                 :           2259 :         u_var.weight += blen;
                              10488                 :           2259 :         add_var(&u_var, &a0_var, &u_var);
                              10489                 :           2259 :         mul_var(&q_var, &q_var, &q_var, 0);
                              10490                 :                : 
                              10491         [ +  + ]:           2259 :         if (step > 0)
                              10492                 :                :         {
                              10493                 :                :             /* Need r for later iterations */
                              10494                 :            897 :             sub_var(&u_var, &q_var, &r_var);
                              10495         [ +  + ]:            897 :             if (r_var.sign == NUMERIC_NEG)
                              10496                 :                :             {
                              10497                 :                :                 /* s is too large by 1; set r += s, s--, r += s */
                              10498                 :             60 :                 add_var(&r_var, &s_var, &r_var);
                              10499                 :             60 :                 sub_var(&s_var, &const_one, &s_var);
                              10500                 :             60 :                 add_var(&r_var, &s_var, &r_var);
                              10501                 :                :             }
                              10502                 :                :         }
                              10503                 :                :         else
                              10504                 :                :         {
                              10505                 :                :             /* Don't need r anymore, except to test if s is too large by 1 */
                              10506         [ +  + ]:           1362 :             if (cmp_var(&u_var, &q_var) < 0)
                              10507                 :             18 :                 sub_var(&s_var, &const_one, &s_var);
                              10508                 :                :         }
                              10509                 :                : 
                              10510         [ -  + ]:           2259 :         Assert(src_idx == src_ndigits); /* All input digits consumed */
                              10511                 :           2259 :         step--;
                              10512                 :                :     }
                              10513                 :                : 
                              10514                 :                :     /*
                              10515                 :                :      * Construct the final result, rounding it to the requested precision.
                              10516                 :                :      */
                              10517                 :           2085 :     set_var_from_var(&s_var, result);
                              10518                 :           2085 :     result->weight = res_weight;
                              10519                 :           2085 :     result->sign = NUMERIC_POS;
                              10520                 :                : 
                              10521                 :                :     /* Round to target rscale (and set result->dscale) */
 7695 tgl@sss.pgh.pa.us       10522                 :           2085 :     round_var(result, rscale);
                              10523                 :                : 
                              10524                 :                :     /* Strip leading and trailing zeroes */
 1478 dean.a.rasheed@gmail    10525                 :           2085 :     strip_var(result);
                              10526                 :                : 
                              10527                 :           2085 :     free_var(&s_var);
                              10528                 :           2085 :     free_var(&r_var);
                              10529                 :           2085 :     free_var(&a0_var);
                              10530                 :           2085 :     free_var(&a1_var);
                              10531                 :           2085 :     free_var(&q_var);
                              10532                 :           2085 :     free_var(&u_var);
                              10533                 :                : }
                              10534                 :                : 
                              10535                 :                : 
                              10536                 :                : /*
                              10537                 :                :  * exp_var() -
                              10538                 :                :  *
                              10539                 :                :  *  Raise e to the power of x, computed to rscale fractional digits
                              10540                 :                :  */
                              10541                 :                : static void
 2408 andres@anarazel.de      10542                 :             90 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
                              10543                 :                : {
                              10544                 :                :     NumericVar  x;
                              10545                 :                :     NumericVar  elem;
                              10546                 :                :     int         ni;
                              10547                 :                :     double      val;
                              10548                 :                :     int         dweight;
                              10549                 :                :     int         ndiv2;
                              10550                 :                :     int         sig_digits;
                              10551                 :                :     int         local_rscale;
                              10552                 :                : 
 9237 JanWieck@Yahoo.com      10553                 :             90 :     init_var(&x);
 3074 tgl@sss.pgh.pa.us       10554                 :             90 :     init_var(&elem);
                              10555                 :                : 
 9237 JanWieck@Yahoo.com      10556                 :             90 :     set_var_from_var(arg, &x);
                              10557                 :                : 
                              10558                 :                :     /*
                              10559                 :                :      * Estimate the dweight of the result using floating point arithmetic, so
                              10560                 :                :      * that we can choose an appropriate local rscale for the calculation.
                              10561                 :                :      */
 3074 tgl@sss.pgh.pa.us       10562                 :             90 :     val = numericvar_to_double_no_overflow(&x);
                              10563                 :                : 
                              10564                 :                :     /* Guard against overflow/underflow */
                              10565                 :                :     /* If you change this limit, see also power_var()'s limit */
  555 peter@eisentraut.org    10566         [ +  + ]:             90 :     if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
                              10567                 :                :     {
  988 dean.a.rasheed@gmail    10568         [ -  + ]:              3 :         if (val > 0)
  988 dean.a.rasheed@gmail    10569         [ #  # ]:UBC           0 :             ereport(ERROR,
                              10570                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              10571                 :                :                      errmsg("value overflows numeric format")));
  988 dean.a.rasheed@gmail    10572                 :CBC           3 :         zero_var(result);
                              10573                 :              3 :         result->dscale = rscale;
                              10574                 :              3 :         return;
                              10575                 :                :     }
                              10576                 :                : 
                              10577                 :                :     /* decimal weight = log10(e^x) = x * log10(e) */
 3074 tgl@sss.pgh.pa.us       10578                 :             87 :     dweight = (int) (val * 0.434294481903252);
                              10579                 :                : 
                              10580                 :                :     /*
                              10581                 :                :      * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
                              10582                 :                :      * 2^ndiv2, to improve the convergence rate of the Taylor series.
                              10583                 :                :      *
                              10584                 :                :      * Note that the overflow check above ensures that fabs(x) < 6000, which
                              10585                 :                :      * means that ndiv2 <= 20 here.
                              10586                 :                :      */
  555 peter@eisentraut.org    10587         [ +  + ]:             87 :     if (fabs(val) > 0.01)
                              10588                 :                :     {
 3074 tgl@sss.pgh.pa.us       10589                 :             72 :         ndiv2 = 1;
                              10590                 :             72 :         val /= 2;
                              10591                 :                : 
  555 peter@eisentraut.org    10592         [ +  + ]:            909 :         while (fabs(val) > 0.01)
                              10593                 :                :         {
 3074 tgl@sss.pgh.pa.us       10594                 :            837 :             ndiv2++;
                              10595                 :            837 :             val /= 2;
                              10596                 :                :         }
                              10597                 :                : 
                              10598                 :             72 :         local_rscale = x.dscale + ndiv2;
  777 dean.a.rasheed@gmail    10599                 :             72 :         div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
                              10600                 :                :     }
                              10601                 :                :     else
 3074 tgl@sss.pgh.pa.us       10602                 :             15 :         ndiv2 = 0;
                              10603                 :                : 
                              10604                 :                :     /*
                              10605                 :                :      * Set the scale for the Taylor series expansion.  The final result has
                              10606                 :                :      * (dweight + rscale + 1) significant digits.  In addition, we have to
                              10607                 :                :      * raise the Taylor series result to the power 2^ndiv2, which introduces
                              10608                 :                :      * an error of up to around log10(2^ndiv2) digits, so work with this many
                              10609                 :                :      * extra digits of precision (plus a few more for good measure).
                              10610                 :                :      */
                              10611                 :             87 :     sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
                              10612                 :             87 :     sig_digits = Max(sig_digits, 0) + 8;
                              10613                 :                : 
                              10614                 :             87 :     local_rscale = sig_digits - 1;
                              10615                 :                : 
                              10616                 :                :     /*
                              10617                 :                :      * Use the Taylor series
                              10618                 :                :      *
                              10619                 :                :      * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
                              10620                 :                :      *
                              10621                 :                :      * Given the limited range of x, this should converge reasonably quickly.
                              10622                 :                :      * We run the series until the terms fall below the local_rscale limit.
                              10623                 :                :      */
 9237 JanWieck@Yahoo.com      10624                 :             87 :     add_var(&const_one, &x, result);
                              10625                 :                : 
 3074 tgl@sss.pgh.pa.us       10626                 :             87 :     mul_var(&x, &x, &elem, local_rscale);
  777 dean.a.rasheed@gmail    10627                 :             87 :     ni = 2;
                              10628                 :             87 :     div_var_int(&elem, ni, 0, &elem, local_rscale, true);
                              10629                 :                : 
 3074 tgl@sss.pgh.pa.us       10630         [ +  + ]:           2496 :     while (elem.ndigits != 0)
                              10631                 :                :     {
 9237 JanWieck@Yahoo.com      10632                 :           2409 :         add_var(result, &elem, result);
                              10633                 :                : 
 3074 tgl@sss.pgh.pa.us       10634                 :           2409 :         mul_var(&elem, &x, &elem, local_rscale);
  777 dean.a.rasheed@gmail    10635                 :           2409 :         ni++;
                              10636                 :           2409 :         div_var_int(&elem, ni, 0, &elem, local_rscale, true);
                              10637                 :                :     }
                              10638                 :                : 
                              10639                 :                :     /*
                              10640                 :                :      * Compensate for the argument range reduction.  Since the weight of the
                              10641                 :                :      * result doubles with each multiplication, we can reduce the local rscale
                              10642                 :                :      * as we proceed.
                              10643                 :                :      */
 9237 JanWieck@Yahoo.com      10644         [ +  + ]:            996 :     while (ndiv2-- > 0)
                              10645                 :                :     {
 3074 tgl@sss.pgh.pa.us       10646                 :            909 :         local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
                              10647                 :            909 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
 7695                         10648                 :            909 :         mul_var(result, result, result, local_rscale);
                              10649                 :                :     }
                              10650                 :                : 
                              10651                 :                :     /* Round to requested rscale */
 3074                         10652                 :             87 :     round_var(result, rscale);
                              10653                 :                : 
 9237 JanWieck@Yahoo.com      10654                 :             87 :     free_var(&x);
                              10655                 :             87 :     free_var(&elem);
                              10656                 :                : }
                              10657                 :                : 
                              10658                 :                : 
                              10659                 :                : /*
                              10660                 :                :  * Estimate the dweight of the most significant decimal digit of the natural
                              10661                 :                :  * logarithm of a number.
                              10662                 :                :  *
                              10663                 :                :  * Essentially, we're approximating log10(abs(ln(var))).  This is used to
                              10664                 :                :  * determine the appropriate rscale when computing natural logarithms.
                              10665                 :                :  *
                              10666                 :                :  * Note: many callers call this before range-checking the input.  Therefore,
                              10667                 :                :  * we must be robust against values that are invalid to apply ln() to.
                              10668                 :                :  * We don't wish to throw an error here, so just return zero in such cases.
                              10669                 :                :  */
                              10670                 :                : static int
 2408 andres@anarazel.de      10671                 :            369 : estimate_ln_dweight(const NumericVar *var)
                              10672                 :                : {
                              10673                 :                :     int         ln_dweight;
                              10674                 :                : 
                              10675                 :                :     /* Caller should fail on ln(negative), but for the moment return zero */
  773 tgl@sss.pgh.pa.us       10676         [ +  + ]:            369 :     if (var->sign != NUMERIC_POS)
                              10677                 :             21 :         return 0;
                              10678                 :                : 
 3074                         10679   [ +  +  +  + ]:            657 :     if (cmp_var(var, &const_zero_point_nine) >= 0 &&
                              10680                 :            309 :         cmp_var(var, &const_one_point_one) <= 0)
                              10681                 :             45 :     {
                              10682                 :                :         /*
                              10683                 :                :          * 0.9 <= var <= 1.1
                              10684                 :                :          *
                              10685                 :                :          * ln(var) has a negative weight (possibly very large).  To get a
                              10686                 :                :          * reasonably accurate result, estimate it using ln(1+x) ~= x.
                              10687                 :                :          */
                              10688                 :                :         NumericVar  x;
                              10689                 :                : 
                              10690                 :             45 :         init_var(&x);
                              10691                 :             45 :         sub_var(var, &const_one, &x);
                              10692                 :                : 
                              10693         [ +  + ]:             45 :         if (x.ndigits > 0)
                              10694                 :                :         {
                              10695                 :                :             /* Use weight of most significant decimal digit of x */
                              10696                 :             21 :             ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
                              10697                 :                :         }
                              10698                 :                :         else
                              10699                 :                :         {
                              10700                 :                :             /* x = 0.  Since ln(1) = 0 exactly, we don't need extra digits */
                              10701                 :             24 :             ln_dweight = 0;
                              10702                 :                :         }
                              10703                 :                : 
                              10704                 :             45 :         free_var(&x);
                              10705                 :                :     }
                              10706                 :                :     else
                              10707                 :                :     {
                              10708                 :                :         /*
                              10709                 :                :          * Estimate the logarithm using the first couple of digits from the
                              10710                 :                :          * input number.  This will give an accurate result whenever the input
                              10711                 :                :          * is not too close to 1.
                              10712                 :                :          */
                              10713         [ +  + ]:            303 :         if (var->ndigits > 0)
                              10714                 :                :         {
                              10715                 :                :             int         digits;
                              10716                 :                :             int         dweight;
                              10717                 :                :             double      ln_var;
                              10718                 :                : 
                              10719                 :            282 :             digits = var->digits[0];
                              10720                 :            282 :             dweight = var->weight * DEC_DIGITS;
                              10721                 :                : 
                              10722         [ +  + ]:            282 :             if (var->ndigits > 1)
                              10723                 :                :             {
                              10724                 :            171 :                 digits = digits * NBASE + var->digits[1];
                              10725                 :            171 :                 dweight -= DEC_DIGITS;
                              10726                 :                :             }
                              10727                 :                : 
                              10728                 :                :             /*----------
                              10729                 :                :              * We have var ~= digits * 10^dweight
                              10730                 :                :              * so ln(var) ~= ln(digits) + dweight * ln(10)
                              10731                 :                :              *----------
                              10732                 :                :              */
                              10733                 :            282 :             ln_var = log((double) digits) + dweight * 2.302585092994046;
  555 peter@eisentraut.org    10734                 :            282 :             ln_dweight = (int) log10(fabs(ln_var));
                              10735                 :                :         }
                              10736                 :                :         else
                              10737                 :                :         {
                              10738                 :                :             /* Caller should fail on ln(0), but for the moment return zero */
 3074 tgl@sss.pgh.pa.us       10739                 :             21 :             ln_dweight = 0;
                              10740                 :                :         }
                              10741                 :                :     }
                              10742                 :                : 
                              10743                 :            348 :     return ln_dweight;
                              10744                 :                : }
                              10745                 :                : 
                              10746                 :                : 
                              10747                 :                : /*
                              10748                 :                :  * ln_var() -
                              10749                 :                :  *
                              10750                 :                :  *  Compute the natural log of x
                              10751                 :                :  */
                              10752                 :                : static void
 2408 andres@anarazel.de      10753                 :            417 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
                              10754                 :                : {
                              10755                 :                :     NumericVar  x;
                              10756                 :                :     NumericVar  xx;
                              10757                 :                :     int         ni;
                              10758                 :                :     NumericVar  elem;
                              10759                 :                :     NumericVar  fact;
                              10760                 :                :     int         nsqrt;
                              10761                 :                :     int         local_rscale;
                              10762                 :                :     int         cmp;
                              10763                 :                : 
 7273 neilc@samurai.com       10764                 :            417 :     cmp = cmp_var(arg, &const_zero);
                              10765         [ +  + ]:            417 :     if (cmp == 0)
 7567 tgl@sss.pgh.pa.us       10766         [ +  - ]:             21 :         ereport(ERROR,
                              10767                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                              10768                 :                :                  errmsg("cannot take logarithm of zero")));
 7273 neilc@samurai.com       10769         [ +  + ]:            396 :     else if (cmp < 0)
                              10770         [ +  - ]:             18 :         ereport(ERROR,
                              10771                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                              10772                 :                :                  errmsg("cannot take logarithm of a negative number")));
                              10773                 :                : 
 9237 JanWieck@Yahoo.com      10774                 :            378 :     init_var(&x);
                              10775                 :            378 :     init_var(&xx);
                              10776                 :            378 :     init_var(&elem);
                              10777                 :            378 :     init_var(&fact);
                              10778                 :                : 
                              10779                 :            378 :     set_var_from_var(arg, &x);
 7695 tgl@sss.pgh.pa.us       10780                 :            378 :     set_var_from_var(&const_two, &fact);
                              10781                 :                : 
                              10782                 :                :     /*
                              10783                 :                :      * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
                              10784                 :                :      *
                              10785                 :                :      * The final logarithm will have up to around rscale+6 significant digits.
                              10786                 :                :      * Each sqrt() will roughly halve the weight of x, so adjust the local
                              10787                 :                :      * rscale as we work so that we keep this many significant digits at each
                              10788                 :                :      * step (plus a few more for good measure).
                              10789                 :                :      *
                              10790                 :                :      * Note that we allow local_rscale < 0 during this input reduction
                              10791                 :                :      * process, which implies rounding before the decimal point.  sqrt_var()
                              10792                 :                :      * explicitly supports this, and it significantly reduces the work
                              10793                 :                :      * required to reduce very large inputs to the required range.  Once the
                              10794                 :                :      * input reduction is complete, x.weight will be 0 and its display scale
                              10795                 :                :      * will be non-negative again.
                              10796                 :                :      */
 1505 dean.a.rasheed@gmail    10797                 :            378 :     nsqrt = 0;
 7865 tgl@sss.pgh.pa.us       10798         [ +  + ]:            534 :     while (cmp_var(&x, &const_zero_point_nine) <= 0)
                              10799                 :                :     {
 3074                         10800                 :            156 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
 7695                         10801                 :            156 :         sqrt_var(&x, &x, local_rscale);
                              10802                 :            156 :         mul_var(&fact, &const_two, &fact, 0);
 1505 dean.a.rasheed@gmail    10803                 :            156 :         nsqrt++;
                              10804                 :                :     }
 7865 tgl@sss.pgh.pa.us       10805         [ +  + ]:           2064 :     while (cmp_var(&x, &const_one_point_one) >= 0)
                              10806                 :                :     {
 3074                         10807                 :           1686 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
 7695                         10808                 :           1686 :         sqrt_var(&x, &x, local_rscale);
                              10809                 :           1686 :         mul_var(&fact, &const_two, &fact, 0);
 1505 dean.a.rasheed@gmail    10810                 :           1686 :         nsqrt++;
                              10811                 :                :     }
                              10812                 :                : 
                              10813                 :                :     /*
                              10814                 :                :      * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
                              10815                 :                :      *
                              10816                 :                :      * z + z^3/3 + z^5/5 + ...
                              10817                 :                :      *
                              10818                 :                :      * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
                              10819                 :                :      * due to the above range-reduction of x.
                              10820                 :                :      *
                              10821                 :                :      * The convergence of this is not as fast as one would like, but is
                              10822                 :                :      * tolerable given that z is small.
                              10823                 :                :      *
                              10824                 :                :      * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
                              10825                 :                :      * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
                              10826                 :                :      * digits of precision (plus a few more for good measure).
                              10827                 :                :      */
                              10828                 :            378 :     local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
                              10829                 :                : 
 9237 JanWieck@Yahoo.com      10830                 :            378 :     sub_var(&x, &const_one, result);
                              10831                 :            378 :     add_var(&x, &const_one, &elem);
 5854 tgl@sss.pgh.pa.us       10832                 :            378 :     div_var_fast(result, &elem, result, local_rscale, true);
 9237 JanWieck@Yahoo.com      10833                 :            378 :     set_var_from_var(result, &xx);
 7695 tgl@sss.pgh.pa.us       10834                 :            378 :     mul_var(result, result, &x, local_rscale);
                              10835                 :                : 
  777 dean.a.rasheed@gmail    10836                 :            378 :     ni = 1;
                              10837                 :                : 
                              10838                 :                :     for (;;)
                              10839                 :                :     {
                              10840                 :           7011 :         ni += 2;
 7695 tgl@sss.pgh.pa.us       10841                 :           7011 :         mul_var(&xx, &x, &xx, local_rscale);
  777 dean.a.rasheed@gmail    10842                 :           7011 :         div_var_int(&xx, ni, 0, &elem, local_rscale, true);
                              10843                 :                : 
 7865 tgl@sss.pgh.pa.us       10844         [ +  + ]:           7011 :         if (elem.ndigits == 0)
 9237 JanWieck@Yahoo.com      10845                 :            378 :             break;
                              10846                 :                : 
                              10847                 :           6633 :         add_var(result, &elem, result);
                              10848                 :                : 
 7559 bruce@momjian.us        10849         [ -  + ]:           6633 :         if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
 7702 tgl@sss.pgh.pa.us       10850                 :UBC           0 :             break;
                              10851                 :                :     }
                              10852                 :                : 
                              10853                 :                :     /* Compensate for argument range reduction, round to requested rscale */
 7695 tgl@sss.pgh.pa.us       10854                 :CBC         378 :     mul_var(result, &fact, result, rscale);
                              10855                 :                : 
 9237 JanWieck@Yahoo.com      10856                 :            378 :     free_var(&x);
                              10857                 :            378 :     free_var(&xx);
                              10858                 :            378 :     free_var(&elem);
                              10859                 :            378 :     free_var(&fact);
                              10860                 :            378 : }
                              10861                 :                : 
                              10862                 :                : 
                              10863                 :                : /*
                              10864                 :                :  * log_var() -
                              10865                 :                :  *
                              10866                 :                :  *  Compute the logarithm of num in a given base.
                              10867                 :                :  *
                              10868                 :                :  *  Note: this routine chooses dscale of the result.
                              10869                 :                :  */
                              10870                 :                : static void
 2408 andres@anarazel.de      10871                 :            108 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
                              10872                 :                : {
                              10873                 :                :     NumericVar  ln_base;
                              10874                 :                :     NumericVar  ln_num;
                              10875                 :                :     int         ln_base_dweight;
                              10876                 :                :     int         ln_num_dweight;
                              10877                 :                :     int         result_dweight;
                              10878                 :                :     int         rscale;
                              10879                 :                :     int         ln_base_rscale;
                              10880                 :                :     int         ln_num_rscale;
                              10881                 :                : 
 9237 JanWieck@Yahoo.com      10882                 :            108 :     init_var(&ln_base);
                              10883                 :            108 :     init_var(&ln_num);
                              10884                 :                : 
                              10885                 :                :     /* Estimated dweights of ln(base), ln(num) and the final result */
 3074 tgl@sss.pgh.pa.us       10886                 :            108 :     ln_base_dweight = estimate_ln_dweight(base);
                              10887                 :            108 :     ln_num_dweight = estimate_ln_dweight(num);
                              10888                 :            108 :     result_dweight = ln_num_dweight - ln_base_dweight;
                              10889                 :                : 
                              10890                 :                :     /*
                              10891                 :                :      * Select the scale of the result so that it will have at least
                              10892                 :                :      * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
                              10893                 :                :      * input's display scale.
                              10894                 :                :      */
                              10895                 :            108 :     rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
 7695                         10896                 :            108 :     rscale = Max(rscale, base->dscale);
                              10897                 :            108 :     rscale = Max(rscale, num->dscale);
                              10898                 :            108 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10899                 :            108 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                              10900                 :                : 
                              10901                 :                :     /*
                              10902                 :                :      * Set the scales for ln(base) and ln(num) so that they each have more
                              10903                 :                :      * significant digits than the final result.
                              10904                 :                :      */
 3074                         10905                 :            108 :     ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
                              10906                 :            108 :     ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10907                 :                : 
                              10908                 :            108 :     ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
                              10909                 :            108 :     ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10910                 :                : 
                              10911                 :                :     /* Form natural logarithms */
                              10912                 :            108 :     ln_var(base, &ln_base, ln_base_rscale);
                              10913                 :             96 :     ln_var(num, &ln_num, ln_num_rscale);
                              10914                 :                : 
                              10915                 :                :     /* Divide and round to the required scale */
 5854                         10916                 :             81 :     div_var_fast(&ln_num, &ln_base, result, rscale, true);
                              10917                 :                : 
 9237 JanWieck@Yahoo.com      10918                 :             78 :     free_var(&ln_num);
                              10919                 :             78 :     free_var(&ln_base);
                              10920                 :             78 : }
                              10921                 :                : 
                              10922                 :                : 
                              10923                 :                : /*
                              10924                 :                :  * power_var() -
                              10925                 :                :  *
                              10926                 :                :  *  Raise base to the power of exp
                              10927                 :                :  *
                              10928                 :                :  *  Note: this routine chooses dscale of the result.
                              10929                 :                :  */
                              10930                 :                : static void
 2408 andres@anarazel.de      10931                 :            693 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
                              10932                 :                : {
                              10933                 :                :     int         res_sign;
                              10934                 :                :     NumericVar  abs_base;
                              10935                 :                :     NumericVar  ln_base;
                              10936                 :                :     NumericVar  ln_num;
                              10937                 :                :     int         ln_dweight;
                              10938                 :                :     int         rscale;
                              10939                 :                :     int         sig_digits;
                              10940                 :                :     int         local_rscale;
                              10941                 :                :     double      val;
                              10942                 :                : 
                              10943                 :                :     /* If exp can be represented as an integer, use power_var_int */
 7695 tgl@sss.pgh.pa.us       10944   [ +  +  +  + ]:            693 :     if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
                              10945                 :                :     {
                              10946                 :                :         /* exact integer, but does it fit in int? */
                              10947                 :                :         int64       expval64;
                              10948                 :                : 
 3313 andres@anarazel.de      10949         [ +  + ]:            630 :         if (numericvar_to_int64(exp, &expval64))
                              10950                 :                :         {
  982 dean.a.rasheed@gmail    10951   [ +  -  +  + ]:            627 :             if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
                              10952                 :                :             {
                              10953                 :                :                 /* Okay, use power_var_int */
  542                         10954                 :            612 :                 power_var_int(base, (int) expval64, exp->dscale, result);
 7695 tgl@sss.pgh.pa.us       10955                 :            606 :                 return;
                              10956                 :                :             }
                              10957                 :                :         }
                              10958                 :                :     }
                              10959                 :                : 
                              10960                 :                :     /*
                              10961                 :                :      * This avoids log(0) for cases of 0 raised to a non-integer.  0 ^ 0 is
                              10962                 :                :      * handled by power_var_int().
                              10963                 :                :      */
 5820 bruce@momjian.us        10964         [ +  + ]:             81 :     if (cmp_var(base, &const_zero) == 0)
                              10965                 :                :     {
                              10966                 :              9 :         set_var_from_var(&const_zero, result);
 2489 tgl@sss.pgh.pa.us       10967                 :              9 :         result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
 5820 bruce@momjian.us        10968                 :              9 :         return;
                              10969                 :                :     }
                              10970                 :                : 
  988 dean.a.rasheed@gmail    10971                 :             72 :     init_var(&abs_base);
 9237 JanWieck@Yahoo.com      10972                 :             72 :     init_var(&ln_base);
                              10973                 :             72 :     init_var(&ln_num);
                              10974                 :                : 
                              10975                 :                :     /*
                              10976                 :                :      * If base is negative, insist that exp be an integer.  The result is then
                              10977                 :                :      * positive if exp is even and negative if exp is odd.
                              10978                 :                :      */
  988 dean.a.rasheed@gmail    10979         [ +  + ]:             72 :     if (base->sign == NUMERIC_NEG)
                              10980                 :                :     {
                              10981                 :                :         /*
                              10982                 :                :          * Check that exp is an integer.  This error code is defined by the
                              10983                 :                :          * SQL standard, and matches other errors in numeric_power().
                              10984                 :                :          */
                              10985   [ +  -  +  + ]:             18 :         if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
                              10986         [ +  - ]:              9 :             ereport(ERROR,
                              10987                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                              10988                 :                :                      errmsg("a negative number raised to a non-integer power yields a complex result")));
                              10989                 :                : 
                              10990                 :                :         /* Test if exp is odd or even */
                              10991   [ +  -  +  + ]:              9 :         if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
                              10992         [ +  + ]:              6 :             (exp->digits[exp->ndigits - 1] & 1))
                              10993                 :              3 :             res_sign = NUMERIC_NEG;
                              10994                 :                :         else
                              10995                 :              6 :             res_sign = NUMERIC_POS;
                              10996                 :                : 
                              10997                 :                :         /* Then work with abs(base) below */
                              10998                 :              9 :         set_var_from_var(base, &abs_base);
                              10999                 :              9 :         abs_base.sign = NUMERIC_POS;
                              11000                 :              9 :         base = &abs_base;
                              11001                 :                :     }
                              11002                 :                :     else
                              11003                 :             54 :         res_sign = NUMERIC_POS;
                              11004                 :                : 
                              11005                 :                :     /*----------
                              11006                 :                :      * Decide on the scale for the ln() calculation.  For this we need an
                              11007                 :                :      * estimate of the weight of the result, which we obtain by doing an
                              11008                 :                :      * initial low-precision calculation of exp * ln(base).
                              11009                 :                :      *
                              11010                 :                :      * We want result = e ^ (exp * ln(base))
                              11011                 :                :      * so result dweight = log10(result) = exp * ln(base) * log10(e)
                              11012                 :                :      *
                              11013                 :                :      * We also perform a crude overflow test here so that we can exit early if
                              11014                 :                :      * the full-precision result is sure to overflow, and to guard against
                              11015                 :                :      * integer overflow when determining the scale for the real calculation.
                              11016                 :                :      * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
                              11017                 :                :      * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
                              11018                 :                :      * Since the values here are only approximations, we apply a small fuzz
                              11019                 :                :      * factor to this overflow test and let exp_var() determine the exact
                              11020                 :                :      * overflow threshold so that it is consistent for all inputs.
                              11021                 :                :      *----------
                              11022                 :                :      */
 3074 tgl@sss.pgh.pa.us       11023                 :             63 :     ln_dweight = estimate_ln_dweight(base);
                              11024                 :                : 
                              11025                 :                :     /*
                              11026                 :                :      * Set the scale for the low-precision calculation, computing ln(base) to
                              11027                 :                :      * around 8 significant digits.  Note that ln_dweight may be as small as
                              11028                 :                :      * -SHRT_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE here.
                              11029                 :                :      */
                              11030                 :             63 :     local_rscale = 8 - ln_dweight;
                              11031                 :             63 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11032                 :                : 
 7695                         11033                 :             63 :     ln_var(base, &ln_base, local_rscale);
                              11034                 :                : 
                              11035                 :             63 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
                              11036                 :                : 
 7865                         11037                 :             63 :     val = numericvar_to_double_no_overflow(&ln_num);
                              11038                 :                : 
                              11039                 :                :     /* initial overflow/underflow test with fuzz factor */
  555 peter@eisentraut.org    11040         [ +  + ]:             63 :     if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
                              11041                 :                :     {
  988 dean.a.rasheed@gmail    11042         [ -  + ]:              3 :         if (val > 0)
  988 dean.a.rasheed@gmail    11043         [ #  # ]:UBC           0 :             ereport(ERROR,
                              11044                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              11045                 :                :                      errmsg("value overflows numeric format")));
  988 dean.a.rasheed@gmail    11046                 :CBC           3 :         zero_var(result);
                              11047                 :              3 :         result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
                              11048                 :              3 :         return;
                              11049                 :                :     }
                              11050                 :                : 
 2901                         11051                 :             60 :     val *= 0.434294481903252;   /* approximate decimal result weight */
                              11052                 :                : 
                              11053                 :                :     /* choose the result scale */
 7695 tgl@sss.pgh.pa.us       11054                 :             60 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
                              11055                 :             60 :     rscale = Max(rscale, base->dscale);
                              11056                 :             60 :     rscale = Max(rscale, exp->dscale);
                              11057                 :             60 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11058                 :             60 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                              11059                 :                : 
                              11060                 :                :     /* significant digits required in the result */
  988 dean.a.rasheed@gmail    11061                 :             60 :     sig_digits = rscale + (int) val;
                              11062                 :             60 :     sig_digits = Max(sig_digits, 0);
                              11063                 :                : 
                              11064                 :                :     /* set the scale for the real exp * ln(base) calculation */
                              11065                 :             60 :     local_rscale = sig_digits - ln_dweight + 8;
 3074 tgl@sss.pgh.pa.us       11066                 :             60 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11067                 :                : 
                              11068                 :                :     /* and do the real calculation */
                              11069                 :                : 
                              11070                 :             60 :     ln_var(base, &ln_base, local_rscale);
                              11071                 :                : 
                              11072                 :             60 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
                              11073                 :                : 
 7695                         11074                 :             60 :     exp_var(&ln_num, result, rscale);
                              11075                 :                : 
  988 dean.a.rasheed@gmail    11076   [ +  +  +  - ]:             60 :     if (res_sign == NUMERIC_NEG && result->ndigits > 0)
                              11077                 :              3 :         result->sign = NUMERIC_NEG;
                              11078                 :                : 
 7695 tgl@sss.pgh.pa.us       11079                 :             60 :     free_var(&ln_num);
                              11080                 :             60 :     free_var(&ln_base);
  988 dean.a.rasheed@gmail    11081                 :             60 :     free_var(&abs_base);
                              11082                 :                : }
                              11083                 :                : 
                              11084                 :                : /*
                              11085                 :                :  * power_var_int() -
                              11086                 :                :  *
                              11087                 :                :  *  Raise base to the power of exp, where exp is an integer.
                              11088                 :                :  *
                              11089                 :                :  *  Note: this routine chooses dscale of the result.
                              11090                 :                :  */
                              11091                 :                : static void
  542                         11092                 :            612 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
                              11093                 :                :               NumericVar *result)
                              11094                 :                : {
                              11095                 :                :     double      f;
                              11096                 :                :     int         p;
                              11097                 :                :     int         i;
                              11098                 :                :     int         rscale;
                              11099                 :                :     int         sig_digits;
                              11100                 :                :     unsigned int mask;
                              11101                 :                :     bool        neg;
                              11102                 :                :     NumericVar  base_prod;
                              11103                 :                :     int         local_rscale;
                              11104                 :                : 
                              11105                 :                :     /*
                              11106                 :                :      * Choose the result scale.  For this we need an estimate of the decimal
                              11107                 :                :      * weight of the result, which we obtain by approximating using double
                              11108                 :                :      * precision arithmetic.
                              11109                 :                :      *
                              11110                 :                :      * We also perform crude overflow/underflow tests here so that we can exit
                              11111                 :                :      * early if the result is sure to overflow/underflow, and to guard against
                              11112                 :                :      * integer overflow when choosing the result scale.
                              11113                 :                :      */
                              11114         [ +  + ]:            612 :     if (base->ndigits != 0)
                              11115                 :                :     {
                              11116                 :                :         /*----------
                              11117                 :                :          * Choose f (double) and p (int) such that base ~= f * 10^p.
                              11118                 :                :          * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
                              11119                 :                :          *----------
                              11120                 :                :          */
                              11121                 :            597 :         f = base->digits[0];
                              11122                 :            597 :         p = base->weight * DEC_DIGITS;
                              11123                 :                : 
                              11124   [ +  +  +  - ]:            639 :         for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
                              11125                 :                :         {
                              11126                 :             42 :             f = f * NBASE + base->digits[i];
                              11127                 :             42 :             p -= DEC_DIGITS;
                              11128                 :                :         }
                              11129                 :                : 
                              11130                 :            597 :         f = exp * (log10(f) + p);   /* approximate decimal result weight */
                              11131                 :                :     }
                              11132                 :                :     else
                              11133                 :             15 :         f = 0;                  /* result is 0 or 1 (weight 0), or error */
                              11134                 :                : 
                              11135                 :                :     /* overflow/underflow tests with fuzz factors */
                              11136         [ +  + ]:            612 :     if (f > (SHRT_MAX + 1) * DEC_DIGITS)
                              11137         [ +  - ]:              6 :         ereport(ERROR,
                              11138                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              11139                 :                :                  errmsg("value overflows numeric format")));
                              11140         [ +  + ]:            606 :     if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
                              11141                 :                :     {
                              11142                 :              6 :         zero_var(result);
                              11143                 :              6 :         result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
                              11144                 :            105 :         return;
                              11145                 :                :     }
                              11146                 :                : 
                              11147                 :                :     /*
                              11148                 :                :      * Choose the result scale in the same way as power_var(), so it has at
                              11149                 :                :      * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
                              11150                 :                :      * either input's display scale.
                              11151                 :                :      */
                              11152                 :            600 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
                              11153                 :            600 :     rscale = Max(rscale, base->dscale);
                              11154                 :            600 :     rscale = Max(rscale, exp_dscale);
                              11155                 :            600 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11156                 :            600 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                              11157                 :                : 
                              11158                 :                :     /* Handle some common special cases, as well as corner cases */
 7695 tgl@sss.pgh.pa.us       11159   [ +  +  +  +  :            600 :     switch (exp)
                                                 + ]
                              11160                 :                :     {
                              11161                 :             36 :         case 0:
                              11162                 :                : 
                              11163                 :                :             /*
                              11164                 :                :              * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
                              11165                 :                :              * it as 1 because most programming languages do this. SQL:2003
                              11166                 :                :              * also requires a return value of 1.
                              11167                 :                :              * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
                              11168                 :                :              */
                              11169                 :             36 :             set_var_from_var(&const_one, result);
 7559 bruce@momjian.us        11170                 :             36 :             result->dscale = rscale; /* no need to round */
 7695 tgl@sss.pgh.pa.us       11171                 :             36 :             return;
                              11172                 :             24 :         case 1:
                              11173                 :             24 :             set_var_from_var(base, result);
                              11174                 :             24 :             round_var(result, rscale);
                              11175                 :             24 :             return;
                              11176                 :             15 :         case -1:
 6889 bruce@momjian.us        11177                 :             15 :             div_var(&const_one, base, result, rscale, true);
 7695 tgl@sss.pgh.pa.us       11178                 :             15 :             return;
                              11179                 :             24 :         case 2:
                              11180                 :             24 :             mul_var(base, base, result, rscale);
                              11181                 :             24 :             return;
                              11182                 :            501 :         default:
                              11183                 :            501 :             break;
                              11184                 :                :     }
                              11185                 :                : 
                              11186                 :                :     /* Handle the special case where the base is zero */
 3074                         11187         [ -  + ]:            501 :     if (base->ndigits == 0)
                              11188                 :                :     {
 3074 tgl@sss.pgh.pa.us       11189         [ #  # ]:UBC           0 :         if (exp < 0)
                              11190         [ #  # ]:              0 :             ereport(ERROR,
                              11191                 :                :                     (errcode(ERRCODE_DIVISION_BY_ZERO),
                              11192                 :                :                      errmsg("division by zero")));
                              11193                 :              0 :         zero_var(result);
                              11194                 :              0 :         result->dscale = rscale;
                              11195                 :              0 :         return;
                              11196                 :                :     }
                              11197                 :                : 
                              11198                 :                :     /*
                              11199                 :                :      * The general case repeatedly multiplies base according to the bit
                              11200                 :                :      * pattern of exp.
                              11201                 :                :      *
                              11202                 :                :      * The local rscale used for each multiplication is varied to keep a fixed
                              11203                 :                :      * number of significant digits, sufficient to give the required result
                              11204                 :                :      * scale.
                              11205                 :                :      */
                              11206                 :                : 
                              11207                 :                :     /*
                              11208                 :                :      * Approximate number of significant digits in the result.  Note that the
                              11209                 :                :      * underflow test above, together with the choice of rscale, ensures that
                              11210                 :                :      * this approximation is necessarily > 0.
                              11211                 :                :      */
 3074 tgl@sss.pgh.pa.us       11212                 :CBC         501 :     sig_digits = 1 + rscale + (int) f;
                              11213                 :                : 
                              11214                 :                :     /*
                              11215                 :                :      * The multiplications to produce the result may introduce an error of up
                              11216                 :                :      * to around log10(abs(exp)) digits, so work with this many extra digits
                              11217                 :                :      * of precision (plus a few more for good measure).
                              11218                 :                :      */
 1195 dean.a.rasheed@gmail    11219                 :            501 :     sig_digits += (int) log(fabs((double) exp)) + 8;
                              11220                 :                : 
                              11221                 :                :     /*
                              11222                 :                :      * Now we can proceed with the multiplications.
                              11223                 :                :      */
 7695 tgl@sss.pgh.pa.us       11224                 :            501 :     neg = (exp < 0);
  555 peter@eisentraut.org    11225                 :            501 :     mask = abs(exp);
                              11226                 :                : 
 7695 tgl@sss.pgh.pa.us       11227                 :            501 :     init_var(&base_prod);
                              11228                 :            501 :     set_var_from_var(base, &base_prod);
                              11229                 :                : 
 3503                         11230         [ +  + ]:            501 :     if (mask & 1)
 7695                         11231                 :            249 :         set_var_from_var(base, result);
                              11232                 :                :     else
                              11233                 :            252 :         set_var_from_var(&const_one, result);
                              11234                 :                : 
 3503                         11235         [ +  + ]:           2532 :     while ((mask >>= 1) > 0)
                              11236                 :                :     {
                              11237                 :                :         /*
                              11238                 :                :          * Do the multiplications using rscales large enough to hold the
                              11239                 :                :          * results to the required number of significant digits, but don't
                              11240                 :                :          * waste time by exceeding the scales of the numbers themselves.
                              11241                 :                :          */
 3074                         11242                 :           2031 :         local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
                              11243                 :           2031 :         local_rscale = Min(local_rscale, 2 * base_prod.dscale);
                              11244                 :           2031 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11245                 :                : 
 7695                         11246                 :           2031 :         mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
                              11247                 :                : 
 3503                         11248         [ +  + ]:           2031 :         if (mask & 1)
                              11249                 :                :         {
 3074                         11250                 :           1326 :             local_rscale = sig_digits -
                              11251                 :           1326 :                 (base_prod.weight + result->weight) * DEC_DIGITS;
                              11252                 :           1326 :             local_rscale = Min(local_rscale,
                              11253                 :                :                                base_prod.dscale + result->dscale);
                              11254                 :           1326 :             local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11255                 :                : 
 7695                         11256                 :           1326 :             mul_var(&base_prod, result, result, local_rscale);
                              11257                 :                :         }
                              11258                 :                : 
                              11259                 :                :         /*
                              11260                 :                :          * When abs(base) > 1, the number of digits to the left of the decimal
                              11261                 :                :          * point in base_prod doubles at each iteration, so if exp is large we
                              11262                 :                :          * could easily spend large amounts of time and memory space doing the
                              11263                 :                :          * multiplications.  But once the weight exceeds what will fit in
                              11264                 :                :          * int16, the final result is guaranteed to overflow (or underflow, if
                              11265                 :                :          * exp < 0), so we can give up before wasting too many cycles.
                              11266                 :                :          */
 3503                         11267   [ +  -  -  + ]:           2031 :         if (base_prod.weight > SHRT_MAX || result->weight > SHRT_MAX)
                              11268                 :                :         {
                              11269                 :                :             /* overflow, unless neg, in which case result should be 0 */
 3503 tgl@sss.pgh.pa.us       11270         [ #  # ]:UBC           0 :             if (!neg)
                              11271         [ #  # ]:              0 :                 ereport(ERROR,
                              11272                 :                :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              11273                 :                :                          errmsg("value overflows numeric format")));
                              11274                 :              0 :             zero_var(result);
                              11275                 :              0 :             neg = false;
                              11276                 :              0 :             break;
                              11277                 :                :         }
                              11278                 :                :     }
                              11279                 :                : 
 7695 tgl@sss.pgh.pa.us       11280                 :CBC         501 :     free_var(&base_prod);
                              11281                 :                : 
                              11282                 :                :     /* Compensate for input sign, and round to requested rscale */
                              11283         [ +  + ]:            501 :     if (neg)
 5854                         11284                 :            240 :         div_var_fast(&const_one, result, result, rscale, true);
                              11285                 :                :     else
 7695                         11286                 :            261 :         round_var(result, rscale);
                              11287                 :                : }
                              11288                 :                : 
                              11289                 :                : /*
                              11290                 :                :  * power_ten_int() -
                              11291                 :                :  *
                              11292                 :                :  *  Raise ten to the power of exp, where exp is an integer.  Note that unlike
                              11293                 :                :  *  power_var_int(), this does no overflow/underflow checking or rounding.
                              11294                 :                :  */
                              11295                 :                : static void
  983 dean.a.rasheed@gmail    11296                 :            108 : power_ten_int(int exp, NumericVar *result)
                              11297                 :                : {
                              11298                 :                :     /* Construct the result directly, starting from 10^0 = 1 */
                              11299                 :            108 :     set_var_from_var(&const_one, result);
                              11300                 :                : 
                              11301                 :                :     /* Scale needed to represent the result exactly */
                              11302         [ +  + ]:            108 :     result->dscale = exp < 0 ? -exp : 0;
                              11303                 :                : 
                              11304                 :                :     /* Base-NBASE weight of result and remaining exponent */
                              11305         [ +  + ]:            108 :     if (exp >= 0)
                              11306                 :             75 :         result->weight = exp / DEC_DIGITS;
                              11307                 :                :     else
                              11308                 :             33 :         result->weight = (exp + 1) / DEC_DIGITS - 1;
                              11309                 :                : 
                              11310                 :            108 :     exp -= result->weight * DEC_DIGITS;
                              11311                 :                : 
                              11312                 :                :     /* Final adjustment of the result's single NBASE digit */
                              11313         [ +  + ]:            273 :     while (exp-- > 0)
                              11314                 :            165 :         result->digits[0] *= 10;
                              11315                 :            108 : }
                              11316                 :                : 
                              11317                 :                : /*
                              11318                 :                :  * random_var() - return a random value in the range [rmin, rmax].
                              11319                 :                :  */
                              11320                 :                : static void
   18 dean.a.rasheed@gmail    11321                 :GNC       16719 : random_var(pg_prng_state *state, const NumericVar *rmin,
                              11322                 :                :            const NumericVar *rmax, NumericVar *result)
                              11323                 :                : {
                              11324                 :                :     int         rscale;
                              11325                 :                :     NumericVar  rlen;
                              11326                 :                :     int         res_ndigits;
                              11327                 :                :     int         n;
                              11328                 :                :     int         pow10;
                              11329                 :                :     int         i;
                              11330                 :                :     uint64      rlen64;
                              11331                 :                :     int         rlen64_ndigits;
                              11332                 :                : 
                              11333                 :          16719 :     rscale = Max(rmin->dscale, rmax->dscale);
                              11334                 :                : 
                              11335                 :                :     /* Compute rlen = rmax - rmin and check the range bounds */
                              11336                 :          16719 :     init_var(&rlen);
                              11337                 :          16719 :     sub_var(rmax, rmin, &rlen);
                              11338                 :                : 
                              11339         [ +  + ]:          16719 :     if (rlen.sign == NUMERIC_NEG)
                              11340         [ +  - ]:              3 :         ereport(ERROR,
                              11341                 :                :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                              11342                 :                :                 errmsg("lower bound must be less than or equal to upper bound"));
                              11343                 :                : 
                              11344                 :                :     /* Special case for an empty range */
                              11345         [ +  + ]:          16716 :     if (rlen.ndigits == 0)
                              11346                 :                :     {
                              11347                 :              6 :         set_var_from_var(rmin, result);
                              11348                 :              6 :         result->dscale = rscale;
                              11349                 :              6 :         free_var(&rlen);
                              11350                 :              6 :         return;
                              11351                 :                :     }
                              11352                 :                : 
                              11353                 :                :     /*
                              11354                 :                :      * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
                              11355                 :                :      * and shift it to the required range by adding rmin.
                              11356                 :                :      */
                              11357                 :                : 
                              11358                 :                :     /* Required result digits */
                              11359                 :          16710 :     res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                              11360                 :                : 
                              11361                 :                :     /*
                              11362                 :                :      * To get the required rscale, the final result digit must be a multiple
                              11363                 :                :      * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
                              11364                 :                :      */
                              11365                 :          16710 :     n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
                              11366                 :          16710 :     pow10 = 1;
                              11367         [ +  + ]:          43950 :     for (i = 0; i < n; i++)
                              11368                 :          27240 :         pow10 *= 10;
                              11369                 :                : 
                              11370                 :                :     /*
                              11371                 :                :      * To choose a random value uniformly from the range [0, rlen], we choose
                              11372                 :                :      * from the slightly larger range [0, rlen2], where rlen2 is formed from
                              11373                 :                :      * rlen by copying the first 4 NBASE digits, and setting all remaining
                              11374                 :                :      * decimal digits to "9".
                              11375                 :                :      *
                              11376                 :                :      * Without loss of generality, we can ignore the weight of rlen2 and treat
                              11377                 :                :      * it as a pure integer for the purposes of this discussion.  The process
                              11378                 :                :      * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
                              11379                 :                :      * is a 64-bit integer formed from the first 4 NBASE digits copied from
                              11380                 :                :      * rlen.  Since this trivially factors into smaller pieces that fit in
                              11381                 :                :      * 64-bit integers, the task of choosing a random value uniformly from the
                              11382                 :                :      * rlen2 + 1 possible values in [0, rlen2] is much simpler.
                              11383                 :                :      *
                              11384                 :                :      * If the random value selected is too large, it is rejected, and we try
                              11385                 :                :      * again until we get a result <= rlen, ensuring that the overall result
                              11386                 :                :      * is uniform (no particular value is any more likely than any other).
                              11387                 :                :      *
                              11388                 :                :      * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
                              11389                 :                :      * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
                              11390                 :                :      * when DEC_DIGITS is 4). Therefore the probability of needing to reject
                              11391                 :                :      * the value chosen and retry is less than 1e-13.
                              11392                 :                :      */
                              11393                 :          16710 :     rlen64 = (uint64) rlen.digits[0];
                              11394                 :          16710 :     rlen64_ndigits = 1;
                              11395   [ +  +  +  + ]:          38106 :     while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
                              11396                 :                :     {
                              11397                 :          21396 :         rlen64 *= NBASE;
                              11398         [ +  + ]:          21396 :         if (rlen64_ndigits < rlen.ndigits)
                              11399                 :           3306 :             rlen64 += rlen.digits[rlen64_ndigits];
                              11400                 :          21396 :         rlen64_ndigits++;
                              11401                 :                :     }
                              11402                 :                : 
                              11403                 :                :     /* Loop until we get a result <= rlen */
                              11404                 :                :     do
                              11405                 :                :     {
                              11406                 :                :         NumericDigit *res_digits;
                              11407                 :                :         uint64      rand;
                              11408                 :                :         int         whole_ndigits;
                              11409                 :                : 
                              11410                 :          16710 :         alloc_var(result, res_ndigits);
                              11411                 :          16710 :         result->sign = NUMERIC_POS;
                              11412                 :          16710 :         result->weight = rlen.weight;
                              11413                 :          16710 :         result->dscale = rscale;
                              11414                 :          16710 :         res_digits = result->digits;
                              11415                 :                : 
                              11416                 :                :         /*
                              11417                 :                :          * Set the first rlen64_ndigits using a random value in [0, rlen64].
                              11418                 :                :          *
                              11419                 :                :          * If this is the whole result, and rscale is not a multiple of
                              11420                 :                :          * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
                              11421                 :                :          * multiple of pow10.
                              11422                 :                :          */
                              11423   [ +  +  +  + ]:          16710 :         if (rlen64_ndigits == res_ndigits && pow10 != 1)
                              11424                 :          10566 :             rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
                              11425                 :                :         else
                              11426                 :           6144 :             rand = pg_prng_uint64_range(state, 0, rlen64);
                              11427                 :                : 
                              11428         [ +  + ]:          54816 :         for (i = rlen64_ndigits - 1; i >= 0; i--)
                              11429                 :                :         {
                              11430                 :          38106 :             res_digits[i] = (NumericDigit) (rand % NBASE);
                              11431                 :          38106 :             rand = rand / NBASE;
                              11432                 :                :         }
                              11433                 :                : 
                              11434                 :                :         /*
                              11435                 :                :          * Set the remaining digits to random values in range [0, NBASE),
                              11436                 :                :          * noting that the last digit needs to be a multiple of pow10.
                              11437                 :                :          */
                              11438                 :          16710 :         whole_ndigits = res_ndigits;
                              11439         [ +  + ]:          16710 :         if (pow10 != 1)
                              11440                 :          16605 :             whole_ndigits--;
                              11441                 :                : 
                              11442                 :                :         /* Set whole digits in groups of 4 for best performance */
                              11443                 :          16710 :         i = rlen64_ndigits;
                              11444         [ +  + ]:          16740 :         while (i < whole_ndigits - 3)
                              11445                 :                :         {
                              11446                 :             30 :             rand = pg_prng_uint64_range(state, 0,
                              11447                 :                :                                         (uint64) NBASE * NBASE * NBASE * NBASE - 1);
                              11448                 :             30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
                              11449                 :             30 :             rand = rand / NBASE;
                              11450                 :             30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
                              11451                 :             30 :             rand = rand / NBASE;
                              11452                 :             30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
                              11453                 :             30 :             rand = rand / NBASE;
                              11454                 :             30 :             res_digits[i++] = (NumericDigit) rand;
                              11455                 :                :         }
                              11456                 :                : 
                              11457                 :                :         /* Remaining whole digits */
                              11458         [ +  + ]:          16815 :         while (i < whole_ndigits)
                              11459                 :                :         {
                              11460                 :            105 :             rand = pg_prng_uint64_range(state, 0, NBASE - 1);
                              11461                 :            105 :             res_digits[i++] = (NumericDigit) rand;
                              11462                 :                :         }
                              11463                 :                : 
                              11464                 :                :         /* Final partial digit (multiple of pow10) */
                              11465         [ +  + ]:          16710 :         if (i < res_ndigits)
                              11466                 :                :         {
                              11467                 :           6039 :             rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
                              11468                 :           6039 :             res_digits[i] = (NumericDigit) rand;
                              11469                 :                :         }
                              11470                 :                : 
                              11471                 :                :         /* Remove leading/trailing zeroes */
                              11472                 :          16710 :         strip_var(result);
                              11473                 :                : 
                              11474                 :                :         /* If result > rlen, try again */
                              11475                 :                : 
                              11476         [ -  + ]:          16710 :     } while (cmp_var(result, &rlen) > 0);
                              11477                 :                : 
                              11478                 :                :     /* Offset the result to the required range */
                              11479                 :          16710 :     add_var(result, rmin, result);
                              11480                 :                : 
                              11481                 :          16710 :     free_var(&rlen);
                              11482                 :                : }
                              11483                 :                : 
                              11484                 :                : 
                              11485                 :                : /* ----------------------------------------------------------------------
                              11486                 :                :  *
                              11487                 :                :  * Following are the lowest level functions that operate unsigned
                              11488                 :                :  * on the variable level
                              11489                 :                :  *
                              11490                 :                :  * ----------------------------------------------------------------------
                              11491                 :                :  */
                              11492                 :                : 
                              11493                 :                : 
                              11494                 :                : /* ----------
                              11495                 :                :  * cmp_abs() -
                              11496                 :                :  *
                              11497                 :                :  *  Compare the absolute values of var1 and var2
                              11498                 :                :  *  Returns:    -1 for ABS(var1) < ABS(var2)
                              11499                 :                :  *              0  for ABS(var1) == ABS(var2)
                              11500                 :                :  *              1  for ABS(var1) > ABS(var2)
                              11501                 :                :  * ----------
                              11502                 :                :  */
                              11503                 :                : static int
 2408 andres@anarazel.de      11504                 :CBC      180036 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
                              11505                 :                : {
 6641 bruce@momjian.us        11506                 :         360072 :     return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
                              11507                 :         180036 :                           var2->digits, var2->ndigits, var2->weight);
                              11508                 :                : }
                              11509                 :                : 
                              11510                 :                : /* ----------
                              11511                 :                :  * cmp_abs_common() -
                              11512                 :                :  *
                              11513                 :                :  *  Main routine of cmp_abs(). This function can be used by both
                              11514                 :                :  *  NumericVar and Numeric.
                              11515                 :                :  * ----------
                              11516                 :                :  */
                              11517                 :                : static int
                              11518                 :        3334689 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
                              11519                 :                :                const NumericDigit *var2digits, int var2ndigits, int var2weight)
                              11520                 :                : {
 9091                         11521                 :        3334689 :     int         i1 = 0;
                              11522                 :        3334689 :     int         i2 = 0;
                              11523                 :                : 
                              11524                 :                :     /* Check any digits before the first common digit */
                              11525                 :                : 
 6641                         11526   [ +  +  +  + ]:        3334689 :     while (var1weight > var2weight && i1 < var1ndigits)
                              11527                 :                :     {
 7695 tgl@sss.pgh.pa.us       11528         [ +  - ]:          15713 :         if (var1digits[i1++] != 0)
 9091 bruce@momjian.us        11529                 :          15713 :             return 1;
 6641 bruce@momjian.us        11530                 :UBC           0 :         var1weight--;
                              11531                 :                :     }
 6641 bruce@momjian.us        11532   [ +  +  +  + ]:CBC     3318976 :     while (var2weight > var1weight && i2 < var2ndigits)
                              11533                 :                :     {
 7695 tgl@sss.pgh.pa.us       11534         [ +  - ]:          17682 :         if (var2digits[i2++] != 0)
 9091 bruce@momjian.us        11535                 :          17682 :             return -1;
 6641 bruce@momjian.us        11536                 :UBC           0 :         var2weight--;
                              11537                 :                :     }
                              11538                 :                : 
                              11539                 :                :     /* At this point, either w1 == w2 or we've run out of digits */
                              11540                 :                : 
 6641 bruce@momjian.us        11541         [ +  + ]:CBC     3301294 :     if (var1weight == var2weight)
                              11542                 :                :     {
                              11543   [ +  +  +  + ]:        6126883 :         while (i1 < var1ndigits && i2 < var2ndigits)
                              11544                 :                :         {
 7695 tgl@sss.pgh.pa.us       11545                 :        4100271 :             int         stat = var1digits[i1++] - var2digits[i2++];
                              11546                 :                : 
 9232 JanWieck@Yahoo.com      11547         [ +  + ]:        4100271 :             if (stat)
                              11548                 :                :             {
                              11549         [ +  + ]:        1271518 :                 if (stat > 0)
                              11550                 :         822161 :                     return 1;
                              11551                 :         449357 :                 return -1;
                              11552                 :                :             }
                              11553                 :                :         }
                              11554                 :                :     }
                              11555                 :                : 
                              11556                 :                :     /*
                              11557                 :                :      * At this point, we've run out of digits on one side or the other; so any
                              11558                 :                :      * remaining nonzero digits imply that side is larger
                              11559                 :                :      */
 6641 bruce@momjian.us        11560         [ +  + ]:        2029926 :     while (i1 < var1ndigits)
                              11561                 :                :     {
 7695 tgl@sss.pgh.pa.us       11562         [ +  + ]:           4193 :         if (var1digits[i1++] != 0)
 9237 JanWieck@Yahoo.com      11563                 :           4043 :             return 1;
                              11564                 :                :     }
 6641 bruce@momjian.us        11565         [ +  + ]:        2025823 :     while (i2 < var2ndigits)
                              11566                 :                :     {
 7695 tgl@sss.pgh.pa.us       11567         [ +  + ]:            461 :         if (var2digits[i2++] != 0)
 9237 JanWieck@Yahoo.com      11568                 :            371 :             return -1;
                              11569                 :                :     }
                              11570                 :                : 
                              11571                 :        2025362 :     return 0;
                              11572                 :                : }
                              11573                 :                : 
                              11574                 :                : 
                              11575                 :                : /*
                              11576                 :                :  * add_abs() -
                              11577                 :                :  *
                              11578                 :                :  *  Add the absolute values of two variables into result.
                              11579                 :                :  *  result might point to one of the operands without danger.
                              11580                 :                :  */
                              11581                 :                : static void
 2408 andres@anarazel.de      11582                 :         165460 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                              11583                 :                : {
                              11584                 :                :     NumericDigit *res_buf;
                              11585                 :                :     NumericDigit *res_digits;
                              11586                 :                :     int         res_ndigits;
                              11587                 :                :     int         res_weight;
                              11588                 :                :     int         res_rscale,
                              11589                 :                :                 rscale1,
                              11590                 :                :                 rscale2;
                              11591                 :                :     int         res_dscale;
                              11592                 :                :     int         i,
                              11593                 :                :                 i1,
                              11594                 :                :                 i2;
 9091 bruce@momjian.us        11595                 :         165460 :     int         carry = 0;
                              11596                 :                : 
                              11597                 :                :     /* copy these values into local vars for speed in inner loop */
 8672 tgl@sss.pgh.pa.us       11598                 :         165460 :     int         var1ndigits = var1->ndigits;
                              11599                 :         165460 :     int         var2ndigits = var2->ndigits;
                              11600                 :         165460 :     NumericDigit *var1digits = var1->digits;
                              11601                 :         165460 :     NumericDigit *var2digits = var2->digits;
                              11602                 :                : 
 8091 bruce@momjian.us        11603                 :         165460 :     res_weight = Max(var1->weight, var2->weight) + 1;
                              11604                 :                : 
                              11605                 :         165460 :     res_dscale = Max(var1->dscale, var2->dscale);
                              11606                 :                : 
                              11607                 :                :     /* Note: here we are figuring rscale in base-NBASE digits */
 7695 tgl@sss.pgh.pa.us       11608                 :         165460 :     rscale1 = var1->ndigits - var1->weight - 1;
                              11609                 :         165460 :     rscale2 = var2->ndigits - var2->weight - 1;
                              11610                 :         165460 :     res_rscale = Max(rscale1, rscale2);
                              11611                 :                : 
 9237 JanWieck@Yahoo.com      11612                 :         165460 :     res_ndigits = res_rscale + res_weight + 1;
 8853 tgl@sss.pgh.pa.us       11613         [ -  + ]:         165460 :     if (res_ndigits <= 0)
 8853 tgl@sss.pgh.pa.us       11614                 :UBC           0 :         res_ndigits = 1;
                              11615                 :                : 
 7695 tgl@sss.pgh.pa.us       11616                 :CBC      165460 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                              11617                 :         165460 :     res_buf[0] = 0;             /* spare digit for later rounding */
                              11618                 :         165460 :     res_digits = res_buf + 1;
                              11619                 :                : 
 9237 JanWieck@Yahoo.com      11620                 :         165460 :     i1 = res_rscale + var1->weight + 1;
                              11621                 :         165460 :     i2 = res_rscale + var2->weight + 1;
                              11622         [ +  + ]:        1659569 :     for (i = res_ndigits - 1; i >= 0; i--)
                              11623                 :                :     {
                              11624                 :        1494109 :         i1--;
                              11625                 :        1494109 :         i2--;
 8672 tgl@sss.pgh.pa.us       11626   [ +  +  +  + ]:        1494109 :         if (i1 >= 0 && i1 < var1ndigits)
                              11627                 :         660220 :             carry += var1digits[i1];
                              11628   [ +  +  +  + ]:        1494109 :         if (i2 >= 0 && i2 < var2ndigits)
                              11629                 :         519524 :             carry += var2digits[i2];
                              11630                 :                : 
 7695                         11631         [ +  + ]:        1494109 :         if (carry >= NBASE)
                              11632                 :                :         {
                              11633                 :         116596 :             res_digits[i] = carry - NBASE;
 8672                         11634                 :         116596 :             carry = 1;
                              11635                 :                :         }
                              11636                 :                :         else
                              11637                 :                :         {
                              11638                 :        1377513 :             res_digits[i] = carry;
                              11639                 :        1377513 :             carry = 0;
                              11640                 :                :         }
                              11641                 :                :     }
                              11642                 :                : 
                              11643         [ -  + ]:         165460 :     Assert(carry == 0);         /* else we failed to allow for carry out */
                              11644                 :                : 
 9237 JanWieck@Yahoo.com      11645         [ +  + ]:         165460 :     digitbuf_free(result->buf);
                              11646                 :         165460 :     result->ndigits = res_ndigits;
 9091 bruce@momjian.us        11647                 :         165460 :     result->buf = res_buf;
                              11648                 :         165460 :     result->digits = res_digits;
                              11649                 :         165460 :     result->weight = res_weight;
                              11650                 :         165460 :     result->dscale = res_dscale;
                              11651                 :                : 
                              11652                 :                :     /* Remove leading/trailing zeroes */
 7695 tgl@sss.pgh.pa.us       11653                 :         165460 :     strip_var(result);
 9237 JanWieck@Yahoo.com      11654                 :         165460 : }
                              11655                 :                : 
                              11656                 :                : 
                              11657                 :                : /*
                              11658                 :                :  * sub_abs()
                              11659                 :                :  *
                              11660                 :                :  *  Subtract the absolute value of var2 from the absolute value of var1
                              11661                 :                :  *  and store in result. result might point to one of the operands
                              11662                 :                :  *  without danger.
                              11663                 :                :  *
                              11664                 :                :  *  ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
                              11665                 :                :  */
                              11666                 :                : static void
 2408 andres@anarazel.de      11667                 :         162611 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                              11668                 :                : {
                              11669                 :                :     NumericDigit *res_buf;
                              11670                 :                :     NumericDigit *res_digits;
                              11671                 :                :     int         res_ndigits;
                              11672                 :                :     int         res_weight;
                              11673                 :                :     int         res_rscale,
                              11674                 :                :                 rscale1,
                              11675                 :                :                 rscale2;
                              11676                 :                :     int         res_dscale;
                              11677                 :                :     int         i,
                              11678                 :                :                 i1,
                              11679                 :                :                 i2;
 9091 bruce@momjian.us        11680                 :         162611 :     int         borrow = 0;
                              11681                 :                : 
                              11682                 :                :     /* copy these values into local vars for speed in inner loop */
 8672 tgl@sss.pgh.pa.us       11683                 :         162611 :     int         var1ndigits = var1->ndigits;
                              11684                 :         162611 :     int         var2ndigits = var2->ndigits;
                              11685                 :         162611 :     NumericDigit *var1digits = var1->digits;
                              11686                 :         162611 :     NumericDigit *var2digits = var2->digits;
                              11687                 :                : 
 9237 JanWieck@Yahoo.com      11688                 :         162611 :     res_weight = var1->weight;
                              11689                 :                : 
 8091 bruce@momjian.us        11690                 :         162611 :     res_dscale = Max(var1->dscale, var2->dscale);
                              11691                 :                : 
                              11692                 :                :     /* Note: here we are figuring rscale in base-NBASE digits */
 7695 tgl@sss.pgh.pa.us       11693                 :         162611 :     rscale1 = var1->ndigits - var1->weight - 1;
                              11694                 :         162611 :     rscale2 = var2->ndigits - var2->weight - 1;
                              11695                 :         162611 :     res_rscale = Max(rscale1, rscale2);
                              11696                 :                : 
 9237 JanWieck@Yahoo.com      11697                 :         162611 :     res_ndigits = res_rscale + res_weight + 1;
 8853 tgl@sss.pgh.pa.us       11698         [ -  + ]:         162611 :     if (res_ndigits <= 0)
 8853 tgl@sss.pgh.pa.us       11699                 :UBC           0 :         res_ndigits = 1;
                              11700                 :                : 
 7695 tgl@sss.pgh.pa.us       11701                 :CBC      162611 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                              11702                 :         162611 :     res_buf[0] = 0;             /* spare digit for later rounding */
                              11703                 :         162611 :     res_digits = res_buf + 1;
                              11704                 :                : 
 9237 JanWieck@Yahoo.com      11705                 :         162611 :     i1 = res_rscale + var1->weight + 1;
                              11706                 :         162611 :     i2 = res_rscale + var2->weight + 1;
                              11707         [ +  + ]:        2260686 :     for (i = res_ndigits - 1; i >= 0; i--)
                              11708                 :                :     {
                              11709                 :        2098075 :         i1--;
                              11710                 :        2098075 :         i2--;
 8672 tgl@sss.pgh.pa.us       11711   [ +  -  +  + ]:        2098075 :         if (i1 >= 0 && i1 < var1ndigits)
                              11712                 :        1912503 :             borrow += var1digits[i1];
                              11713   [ +  +  +  + ]:        2098075 :         if (i2 >= 0 && i2 < var2ndigits)
                              11714                 :        1860949 :             borrow -= var2digits[i2];
                              11715                 :                : 
 9237 JanWieck@Yahoo.com      11716         [ +  + ]:        2098075 :         if (borrow < 0)
                              11717                 :                :         {
 7695 tgl@sss.pgh.pa.us       11718                 :         211005 :             res_digits[i] = borrow + NBASE;
 9237 JanWieck@Yahoo.com      11719                 :         211005 :             borrow = -1;
                              11720                 :                :         }
                              11721                 :                :         else
                              11722                 :                :         {
                              11723                 :        1887070 :             res_digits[i] = borrow;
                              11724                 :        1887070 :             borrow = 0;
                              11725                 :                :         }
                              11726                 :                :     }
                              11727                 :                : 
 8672 tgl@sss.pgh.pa.us       11728         [ -  + ]:         162611 :     Assert(borrow == 0);        /* else caller gave us var1 < var2 */
                              11729                 :                : 
 9237 JanWieck@Yahoo.com      11730         [ +  + ]:         162611 :     digitbuf_free(result->buf);
                              11731                 :         162611 :     result->ndigits = res_ndigits;
 9091 bruce@momjian.us        11732                 :         162611 :     result->buf = res_buf;
                              11733                 :         162611 :     result->digits = res_digits;
                              11734                 :         162611 :     result->weight = res_weight;
                              11735                 :         162611 :     result->dscale = res_dscale;
                              11736                 :                : 
                              11737                 :                :     /* Remove leading/trailing zeroes */
 7695 tgl@sss.pgh.pa.us       11738                 :         162611 :     strip_var(result);
                              11739                 :         162611 : }
                              11740                 :                : 
                              11741                 :                : /*
                              11742                 :                :  * round_var
                              11743                 :                :  *
                              11744                 :                :  * Round the value of a variable to no more than rscale decimal digits
                              11745                 :                :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
                              11746                 :                :  * rounding before the decimal point.
                              11747                 :                :  */
                              11748                 :                : static void
                              11749                 :         514390 : round_var(NumericVar *var, int rscale)
                              11750                 :                : {
 7559 bruce@momjian.us        11751                 :         514390 :     NumericDigit *digits = var->digits;
                              11752                 :                :     int         di;
                              11753                 :                :     int         ndigits;
                              11754                 :                :     int         carry;
                              11755                 :                : 
 7695 tgl@sss.pgh.pa.us       11756                 :         514390 :     var->dscale = rscale;
                              11757                 :                : 
                              11758                 :                :     /* decimal digits wanted */
                              11759                 :         514390 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
                              11760                 :                : 
                              11761                 :                :     /*
                              11762                 :                :      * If di = 0, the value loses all digits, but could round up to 1 if its
                              11763                 :                :      * first extra digit is >= 5.  If di < 0 the result must be 0.
                              11764                 :                :      */
                              11765         [ +  + ]:         514390 :     if (di < 0)
                              11766                 :                :     {
                              11767                 :             37 :         var->ndigits = 0;
                              11768                 :             37 :         var->weight = 0;
                              11769                 :             37 :         var->sign = NUMERIC_POS;
                              11770                 :                :     }
                              11771                 :                :     else
                              11772                 :                :     {
                              11773                 :                :         /* NBASE digits wanted */
 7559 bruce@momjian.us        11774                 :         514353 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
                              11775                 :                : 
                              11776                 :                :         /* 0, or number of decimal digits to keep in last NBASE digit */
 7695 tgl@sss.pgh.pa.us       11777                 :         514353 :         di %= DEC_DIGITS;
                              11778                 :                : 
                              11779         [ +  + ]:         514353 :         if (ndigits < var->ndigits ||
                              11780   [ +  +  +  + ]:         412714 :             (ndigits == var->ndigits && di > 0))
                              11781                 :                :         {
                              11782                 :         345035 :             var->ndigits = ndigits;
                              11783                 :                : 
                              11784                 :                : #if DEC_DIGITS == 1
                              11785                 :                :             /* di must be zero */
                              11786                 :                :             carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
                              11787                 :                : #else
                              11788         [ +  + ]:         345035 :             if (di == 0)
                              11789                 :          82354 :                 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
                              11790                 :                :             else
                              11791                 :                :             {
                              11792                 :                :                 /* Must round within last NBASE digit */
                              11793                 :                :                 int         extra,
                              11794                 :                :                             pow10;
                              11795                 :                : 
                              11796                 :                : #if DEC_DIGITS == 4
                              11797                 :         262681 :                 pow10 = round_powers[di];
                              11798                 :                : #elif DEC_DIGITS == 2
                              11799                 :                :                 pow10 = 10;
                              11800                 :                : #else
                              11801                 :                : #error unsupported NBASE
                              11802                 :                : #endif
                              11803                 :         262681 :                 extra = digits[--ndigits] % pow10;
                              11804                 :         262681 :                 digits[ndigits] -= extra;
                              11805                 :         262681 :                 carry = 0;
 7559 bruce@momjian.us        11806         [ +  + ]:         262681 :                 if (extra >= pow10 / 2)
                              11807                 :                :                 {
 7695 tgl@sss.pgh.pa.us       11808                 :           9737 :                     pow10 += digits[ndigits];
                              11809         [ +  + ]:           9737 :                     if (pow10 >= NBASE)
                              11810                 :                :                     {
                              11811                 :            406 :                         pow10 -= NBASE;
                              11812                 :            406 :                         carry = 1;
                              11813                 :                :                     }
                              11814                 :           9737 :                     digits[ndigits] = pow10;
                              11815                 :                :                 }
                              11816                 :                :             }
                              11817                 :                : #endif
                              11818                 :                : 
                              11819                 :                :             /* Propagate carry if needed */
                              11820         [ +  + ]:         362701 :             while (carry)
                              11821                 :                :             {
                              11822                 :          17666 :                 carry += digits[--ndigits];
                              11823         [ +  + ]:          17666 :                 if (carry >= NBASE)
                              11824                 :                :                 {
                              11825                 :          12387 :                     digits[ndigits] = carry - NBASE;
                              11826                 :          12387 :                     carry = 1;
                              11827                 :                :                 }
                              11828                 :                :                 else
                              11829                 :                :                 {
                              11830                 :           5279 :                     digits[ndigits] = carry;
                              11831                 :           5279 :                     carry = 0;
                              11832                 :                :                 }
                              11833                 :                :             }
                              11834                 :                : 
                              11835         [ +  + ]:         345035 :             if (ndigits < 0)
                              11836                 :                :             {
                              11837         [ -  + ]:             45 :                 Assert(ndigits == -1);  /* better not have added > 1 digit */
                              11838         [ -  + ]:             45 :                 Assert(var->digits > var->buf);
                              11839                 :             45 :                 var->digits--;
                              11840                 :             45 :                 var->ndigits++;
                              11841                 :             45 :                 var->weight++;
                              11842                 :                :             }
                              11843                 :                :         }
                              11844                 :                :     }
                              11845                 :         514390 : }
                              11846                 :                : 
                              11847                 :                : /*
                              11848                 :                :  * trunc_var
                              11849                 :                :  *
                              11850                 :                :  * Truncate (towards zero) the value of a variable at rscale decimal digits
                              11851                 :                :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
                              11852                 :                :  * truncation before the decimal point.
                              11853                 :                :  */
                              11854                 :                : static void
                              11855                 :          30761 : trunc_var(NumericVar *var, int rscale)
                              11856                 :                : {
                              11857                 :                :     int         di;
                              11858                 :                :     int         ndigits;
                              11859                 :                : 
                              11860                 :          30761 :     var->dscale = rscale;
                              11861                 :                : 
                              11862                 :                :     /* decimal digits wanted */
                              11863                 :          30761 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
                              11864                 :                : 
                              11865                 :                :     /*
                              11866                 :                :      * If di <= 0, the value loses all digits.
                              11867                 :                :      */
                              11868         [ +  + ]:          30761 :     if (di <= 0)
                              11869                 :                :     {
                              11870                 :             27 :         var->ndigits = 0;
                              11871                 :             27 :         var->weight = 0;
                              11872                 :             27 :         var->sign = NUMERIC_POS;
                              11873                 :                :     }
                              11874                 :                :     else
                              11875                 :                :     {
                              11876                 :                :         /* NBASE digits wanted */
 7559 bruce@momjian.us        11877                 :          30734 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
                              11878                 :                : 
 7695 tgl@sss.pgh.pa.us       11879         [ +  + ]:          30734 :         if (ndigits <= var->ndigits)
                              11880                 :                :         {
                              11881                 :          30599 :             var->ndigits = ndigits;
                              11882                 :                : 
                              11883                 :                : #if DEC_DIGITS == 1
                              11884                 :                :             /* no within-digit stuff to worry about */
                              11885                 :                : #else
                              11886                 :                :             /* 0, or number of decimal digits to keep in last NBASE digit */
                              11887                 :          30599 :             di %= DEC_DIGITS;
                              11888                 :                : 
                              11889         [ +  + ]:          30599 :             if (di > 0)
                              11890                 :                :             {
                              11891                 :                :                 /* Must truncate within last NBASE digit */
 7559 bruce@momjian.us        11892                 :             41 :                 NumericDigit *digits = var->digits;
                              11893                 :                :                 int         extra,
                              11894                 :                :                             pow10;
                              11895                 :                : 
                              11896                 :                : #if DEC_DIGITS == 4
 7695 tgl@sss.pgh.pa.us       11897                 :             41 :                 pow10 = round_powers[di];
                              11898                 :                : #elif DEC_DIGITS == 2
                              11899                 :                :                 pow10 = 10;
                              11900                 :                : #else
                              11901                 :                : #error unsupported NBASE
                              11902                 :                : #endif
                              11903                 :             41 :                 extra = digits[--ndigits] % pow10;
                              11904                 :             41 :                 digits[ndigits] -= extra;
                              11905                 :                :             }
                              11906                 :                : #endif
                              11907                 :                :         }
                              11908                 :                :     }
                              11909                 :          30761 : }
                              11910                 :                : 
                              11911                 :                : /*
                              11912                 :                :  * strip_var
                              11913                 :                :  *
                              11914                 :                :  * Strip any leading and trailing zeroes from a numeric variable
                              11915                 :                :  */
                              11916                 :                : static void
                              11917                 :        1034280 : strip_var(NumericVar *var)
                              11918                 :                : {
 7559 bruce@momjian.us        11919                 :        1034280 :     NumericDigit *digits = var->digits;
 7695 tgl@sss.pgh.pa.us       11920                 :        1034280 :     int         ndigits = var->ndigits;
                              11921                 :                : 
                              11922                 :                :     /* Strip leading zeroes */
                              11923   [ +  +  +  + ]:        2364325 :     while (ndigits > 0 && *digits == 0)
                              11924                 :                :     {
                              11925                 :        1330045 :         digits++;
                              11926                 :        1330045 :         var->weight--;
                              11927                 :        1330045 :         ndigits--;
                              11928                 :                :     }
                              11929                 :                : 
                              11930                 :                :     /* Strip trailing zeroes */
                              11931   [ +  +  +  + ]:        1369235 :     while (ndigits > 0 && digits[ndigits - 1] == 0)
                              11932                 :         334955 :         ndigits--;
                              11933                 :                : 
                              11934                 :                :     /* If it's zero, normalize the sign and weight */
                              11935         [ +  + ]:        1034280 :     if (ndigits == 0)
                              11936                 :                :     {
                              11937                 :          13700 :         var->sign = NUMERIC_POS;
                              11938                 :          13700 :         var->weight = 0;
                              11939                 :                :     }
                              11940                 :                : 
                              11941                 :        1034280 :     var->digits = digits;
                              11942                 :        1034280 :     var->ndigits = ndigits;
 9237 JanWieck@Yahoo.com      11943                 :        1034280 : }
                              11944                 :                : 
                              11945                 :                : 
                              11946                 :                : /* ----------------------------------------------------------------------
                              11947                 :                :  *
                              11948                 :                :  * Fast sum accumulator functions
                              11949                 :                :  *
                              11950                 :                :  * ----------------------------------------------------------------------
                              11951                 :                :  */
                              11952                 :                : 
                              11953                 :                : /*
                              11954                 :                :  * Reset the accumulator's value to zero.  The buffers to hold the digits
                              11955                 :                :  * are not free'd.
                              11956                 :                :  */
                              11957                 :                : static void
 2781 heikki.linnakangas@i    11958                 :              9 : accum_sum_reset(NumericSumAccum *accum)
                              11959                 :                : {
                              11960                 :                :     int         i;
                              11961                 :                : 
                              11962                 :              9 :     accum->dscale = 0;
                              11963         [ +  + ]:             33 :     for (i = 0; i < accum->ndigits; i++)
                              11964                 :                :     {
                              11965                 :             24 :         accum->pos_digits[i] = 0;
                              11966                 :             24 :         accum->neg_digits[i] = 0;
                              11967                 :                :     }
                              11968                 :              9 : }
                              11969                 :                : 
                              11970                 :                : /*
                              11971                 :                :  * Accumulate a new value.
                              11972                 :                :  */
                              11973                 :                : static void
 2408 andres@anarazel.de      11974                 :        1177858 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
                              11975                 :                : {
                              11976                 :                :     int32      *accum_digits;
                              11977                 :                :     int         i,
                              11978                 :                :                 val_i;
                              11979                 :                :     int         val_ndigits;
                              11980                 :                :     NumericDigit *val_digits;
                              11981                 :                : 
                              11982                 :                :     /*
                              11983                 :                :      * If we have accumulated too many values since the last carry
                              11984                 :                :      * propagation, do it now, to avoid overflowing.  (We could allow more
                              11985                 :                :      * than NBASE - 1, if we reserved two extra digits, rather than one, for
                              11986                 :                :      * carry propagation.  But even with NBASE - 1, this needs to be done so
                              11987                 :                :      * seldom, that the performance difference is negligible.)
                              11988                 :                :      */
 2781 heikki.linnakangas@i    11989         [ +  + ]:        1177858 :     if (accum->num_uncarried == NBASE - 1)
                              11990                 :             78 :         accum_sum_carry(accum);
                              11991                 :                : 
                              11992                 :                :     /*
                              11993                 :                :      * Adjust the weight or scale of the old value, so that it can accommodate
                              11994                 :                :      * the new value.
                              11995                 :                :      */
                              11996                 :        1177858 :     accum_sum_rescale(accum, val);
                              11997                 :                : 
                              11998                 :                :     /* */
                              11999         [ +  + ]:        1177858 :     if (val->sign == NUMERIC_POS)
                              12000                 :         877519 :         accum_digits = accum->pos_digits;
                              12001                 :                :     else
                              12002                 :         300339 :         accum_digits = accum->neg_digits;
                              12003                 :                : 
                              12004                 :                :     /* copy these values into local vars for speed in loop */
                              12005                 :        1177858 :     val_ndigits = val->ndigits;
                              12006                 :        1177858 :     val_digits = val->digits;
                              12007                 :                : 
                              12008                 :        1177858 :     i = accum->weight - val->weight;
                              12009         [ +  + ]:        5944987 :     for (val_i = 0; val_i < val_ndigits; val_i++)
                              12010                 :                :     {
                              12011                 :        4767129 :         accum_digits[i] += (int32) val_digits[val_i];
                              12012                 :        4767129 :         i++;
                              12013                 :                :     }
                              12014                 :                : 
                              12015                 :        1177858 :     accum->num_uncarried++;
                              12016                 :        1177858 : }
                              12017                 :                : 
                              12018                 :                : /*
                              12019                 :                :  * Propagate carries.
                              12020                 :                :  */
                              12021                 :                : static void
                              12022                 :          86385 : accum_sum_carry(NumericSumAccum *accum)
                              12023                 :                : {
                              12024                 :                :     int         i;
                              12025                 :                :     int         ndigits;
                              12026                 :                :     int32      *dig;
                              12027                 :                :     int32       carry;
                              12028                 :          86385 :     int32       newdig = 0;
                              12029                 :                : 
                              12030                 :                :     /*
                              12031                 :                :      * If no new values have been added since last carry propagation, nothing
                              12032                 :                :      * to do.
                              12033                 :                :      */
                              12034         [ +  + ]:          86385 :     if (accum->num_uncarried == 0)
                              12035                 :             36 :         return;
                              12036                 :                : 
                              12037                 :                :     /*
                              12038                 :                :      * We maintain that the weight of the accumulator is always one larger
                              12039                 :                :      * than needed to hold the current value, before carrying, to make sure
                              12040                 :                :      * there is enough space for the possible extra digit when carry is
                              12041                 :                :      * propagated.  We cannot expand the buffer here, unless we require
                              12042                 :                :      * callers of accum_sum_final() to switch to the right memory context.
                              12043                 :                :      */
                              12044   [ +  -  -  + ]:          86349 :     Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
                              12045                 :                : 
                              12046                 :          86349 :     ndigits = accum->ndigits;
                              12047                 :                : 
                              12048                 :                :     /* Propagate carry in the positive sum */
                              12049                 :          86349 :     dig = accum->pos_digits;
                              12050                 :          86349 :     carry = 0;
                              12051         [ +  + ]:        1302785 :     for (i = ndigits - 1; i >= 0; i--)
                              12052                 :                :     {
                              12053                 :        1216436 :         newdig = dig[i] + carry;
                              12054         [ +  + ]:        1216436 :         if (newdig >= NBASE)
                              12055                 :                :         {
                              12056                 :          55407 :             carry = newdig / NBASE;
                              12057                 :          55407 :             newdig -= carry * NBASE;
                              12058                 :                :         }
                              12059                 :                :         else
                              12060                 :        1161029 :             carry = 0;
                              12061                 :        1216436 :         dig[i] = newdig;
                              12062                 :                :     }
                              12063                 :                :     /* Did we use up the digit reserved for carry propagation? */
                              12064         [ +  + ]:          86349 :     if (newdig > 0)
                              12065                 :           1320 :         accum->have_carry_space = false;
                              12066                 :                : 
                              12067                 :                :     /* And the same for the negative sum */
                              12068                 :          86349 :     dig = accum->neg_digits;
                              12069                 :          86349 :     carry = 0;
                              12070         [ +  + ]:        1302785 :     for (i = ndigits - 1; i >= 0; i--)
                              12071                 :                :     {
                              12072                 :        1216436 :         newdig = dig[i] + carry;
                              12073         [ +  + ]:        1216436 :         if (newdig >= NBASE)
                              12074                 :                :         {
                              12075                 :             99 :             carry = newdig / NBASE;
                              12076                 :             99 :             newdig -= carry * NBASE;
                              12077                 :                :         }
                              12078                 :                :         else
                              12079                 :        1216337 :             carry = 0;
                              12080                 :        1216436 :         dig[i] = newdig;
                              12081                 :                :     }
                              12082         [ +  + ]:          86349 :     if (newdig > 0)
                              12083                 :             15 :         accum->have_carry_space = false;
                              12084                 :                : 
                              12085                 :          86349 :     accum->num_uncarried = 0;
                              12086                 :                : }
                              12087                 :                : 
                              12088                 :                : /*
                              12089                 :                :  * Re-scale accumulator to accommodate new value.
                              12090                 :                :  *
                              12091                 :                :  * If the new value has more digits than the current digit buffers in the
                              12092                 :                :  * accumulator, enlarge the buffers.
                              12093                 :                :  */
                              12094                 :                : static void
 2408 andres@anarazel.de      12095                 :        1177858 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
                              12096                 :                : {
 2781 heikki.linnakangas@i    12097                 :        1177858 :     int         old_weight = accum->weight;
                              12098                 :        1177858 :     int         old_ndigits = accum->ndigits;
                              12099                 :                :     int         accum_ndigits;
                              12100                 :                :     int         accum_weight;
                              12101                 :                :     int         accum_rscale;
                              12102                 :                :     int         val_rscale;
                              12103                 :                : 
                              12104                 :        1177858 :     accum_weight = old_weight;
                              12105                 :        1177858 :     accum_ndigits = old_ndigits;
                              12106                 :                : 
                              12107                 :                :     /*
                              12108                 :                :      * Does the new value have a larger weight? If so, enlarge the buffers,
                              12109                 :                :      * and shift the existing value to the new weight, by adding leading
                              12110                 :                :      * zeros.
                              12111                 :                :      *
                              12112                 :                :      * We enforce that the accumulator always has a weight one larger than
                              12113                 :                :      * needed for the inputs, so that we have space for an extra digit at the
                              12114                 :                :      * final carry-propagation phase, if necessary.
                              12115                 :                :      */
                              12116         [ +  + ]:        1177858 :     if (val->weight >= accum_weight)
                              12117                 :                :     {
                              12118                 :         131118 :         accum_weight = val->weight + 1;
                              12119                 :         131118 :         accum_ndigits = accum_ndigits + (accum_weight - old_weight);
                              12120                 :                :     }
                              12121                 :                : 
                              12122                 :                :     /*
                              12123                 :                :      * Even though the new value is small, we might've used up the space
                              12124                 :                :      * reserved for the carry digit in the last call to accum_sum_carry().  If
                              12125                 :                :      * so, enlarge to make room for another one.
                              12126                 :                :      */
                              12127         [ +  + ]:        1046740 :     else if (!accum->have_carry_space)
                              12128                 :                :     {
                              12129                 :             42 :         accum_weight++;
                              12130                 :             42 :         accum_ndigits++;
                              12131                 :                :     }
                              12132                 :                : 
                              12133                 :                :     /* Is the new value wider on the right side? */
                              12134                 :        1177858 :     accum_rscale = accum_ndigits - accum_weight - 1;
                              12135                 :        1177858 :     val_rscale = val->ndigits - val->weight - 1;
                              12136         [ +  + ]:        1177858 :     if (val_rscale > accum_rscale)
                              12137                 :          86129 :         accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
                              12138                 :                : 
                              12139   [ +  +  -  + ]:        1177858 :     if (accum_ndigits != old_ndigits ||
                              12140                 :                :         accum_weight != old_weight)
                              12141                 :                :     {
                              12142                 :                :         int32      *new_pos_digits;
                              12143                 :                :         int32      *new_neg_digits;
                              12144                 :                :         int         weightdiff;
                              12145                 :                : 
                              12146                 :         131298 :         weightdiff = accum_weight - old_weight;
                              12147                 :                : 
                              12148                 :         131298 :         new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
                              12149                 :         131298 :         new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
                              12150                 :                : 
                              12151         [ +  + ]:         131298 :         if (accum->pos_digits)
                              12152                 :                :         {
                              12153                 :          45204 :             memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
                              12154                 :                :                    old_ndigits * sizeof(int32));
                              12155                 :          45204 :             pfree(accum->pos_digits);
                              12156                 :                : 
                              12157                 :          45204 :             memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
                              12158                 :                :                    old_ndigits * sizeof(int32));
                              12159                 :          45204 :             pfree(accum->neg_digits);
                              12160                 :                :         }
                              12161                 :                : 
                              12162                 :         131298 :         accum->pos_digits = new_pos_digits;
                              12163                 :         131298 :         accum->neg_digits = new_neg_digits;
                              12164                 :                : 
                              12165                 :         131298 :         accum->weight = accum_weight;
                              12166                 :         131298 :         accum->ndigits = accum_ndigits;
                              12167                 :                : 
                              12168   [ +  -  -  + ]:         131298 :         Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
                              12169                 :         131298 :         accum->have_carry_space = true;
                              12170                 :                :     }
                              12171                 :                : 
                              12172         [ +  + ]:        1177858 :     if (val->dscale > accum->dscale)
                              12173                 :            150 :         accum->dscale = val->dscale;
                              12174                 :        1177858 : }
                              12175                 :                : 
                              12176                 :                : /*
                              12177                 :                :  * Return the current value of the accumulator.  This perform final carry
                              12178                 :                :  * propagation, and adds together the positive and negative sums.
                              12179                 :                :  *
                              12180                 :                :  * Unlike all the other routines, the caller is not required to switch to
                              12181                 :                :  * the memory context that holds the accumulator.
                              12182                 :                :  */
                              12183                 :                : static void
                              12184                 :          86307 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
                              12185                 :                : {
                              12186                 :                :     int         i;
                              12187                 :                :     NumericVar  pos_var;
                              12188                 :                :     NumericVar  neg_var;
                              12189                 :                : 
                              12190         [ -  + ]:          86307 :     if (accum->ndigits == 0)
                              12191                 :                :     {
 2781 heikki.linnakangas@i    12192                 :UBC           0 :         set_var_from_var(&const_zero, result);
                              12193                 :              0 :         return;
                              12194                 :                :     }
                              12195                 :                : 
                              12196                 :                :     /* Perform final carry */
 2781 heikki.linnakangas@i    12197                 :CBC       86307 :     accum_sum_carry(accum);
                              12198                 :                : 
                              12199                 :                :     /* Create NumericVars representing the positive and negative sums */
                              12200                 :          86307 :     init_var(&pos_var);
                              12201                 :          86307 :     init_var(&neg_var);
                              12202                 :                : 
                              12203                 :          86307 :     pos_var.ndigits = neg_var.ndigits = accum->ndigits;
                              12204                 :          86307 :     pos_var.weight = neg_var.weight = accum->weight;
                              12205                 :          86307 :     pos_var.dscale = neg_var.dscale = accum->dscale;
                              12206                 :          86307 :     pos_var.sign = NUMERIC_POS;
                              12207                 :          86307 :     neg_var.sign = NUMERIC_NEG;
                              12208                 :                : 
                              12209                 :          86307 :     pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
                              12210                 :          86307 :     neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
                              12211                 :                : 
                              12212         [ +  + ]:        1302569 :     for (i = 0; i < accum->ndigits; i++)
                              12213                 :                :     {
                              12214         [ -  + ]:        1216262 :         Assert(accum->pos_digits[i] < NBASE);
                              12215                 :        1216262 :         pos_var.digits[i] = (int16) accum->pos_digits[i];
                              12216                 :                : 
                              12217         [ -  + ]:        1216262 :         Assert(accum->neg_digits[i] < NBASE);
                              12218                 :        1216262 :         neg_var.digits[i] = (int16) accum->neg_digits[i];
                              12219                 :                :     }
                              12220                 :                : 
                              12221                 :                :     /* And add them together */
                              12222                 :          86307 :     add_var(&pos_var, &neg_var, result);
                              12223                 :                : 
                              12224                 :                :     /* Remove leading/trailing zeroes */
                              12225                 :          86307 :     strip_var(result);
                              12226                 :                : }
                              12227                 :                : 
                              12228                 :                : /*
                              12229                 :                :  * Copy an accumulator's state.
                              12230                 :                :  *
                              12231                 :                :  * 'dst' is assumed to be uninitialized beforehand.  No attempt is made at
                              12232                 :                :  * freeing old values.
                              12233                 :                :  */
                              12234                 :                : static void
                              12235                 :             21 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
                              12236                 :                : {
                              12237                 :             21 :     dst->pos_digits = palloc(src->ndigits * sizeof(int32));
                              12238                 :             21 :     dst->neg_digits = palloc(src->ndigits * sizeof(int32));
                              12239                 :                : 
                              12240                 :             21 :     memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
                              12241                 :             21 :     memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
                              12242                 :             21 :     dst->num_uncarried = src->num_uncarried;
                              12243                 :             21 :     dst->ndigits = src->ndigits;
                              12244                 :             21 :     dst->weight = src->weight;
                              12245                 :             21 :     dst->dscale = src->dscale;
                              12246                 :             21 : }
                              12247                 :                : 
                              12248                 :                : /*
                              12249                 :                :  * Add the current value of 'accum2' into 'accum'.
                              12250                 :                :  */
                              12251                 :                : static void
                              12252                 :             27 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
                              12253                 :                : {
                              12254                 :                :     NumericVar  tmp_var;
                              12255                 :                : 
                              12256                 :             27 :     init_var(&tmp_var);
                              12257                 :                : 
                              12258                 :             27 :     accum_sum_final(accum2, &tmp_var);
                              12259                 :             27 :     accum_sum_add(accum, &tmp_var);
                              12260                 :                : 
                              12261                 :             27 :     free_var(&tmp_var);
                              12262                 :             27 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622