LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - numeric.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GIC GNC CBC EUB ECB DUB DCB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 94.7 % 4018 3807 1 210 117 3690 22 170
Current Date: 2025-09-06 07:49:51 +0900 Functions: 99.5 % 211 210 1 44 166 12
Baseline: lcov-20250906-005545-baseline Branches: 78.6 % 2497 1963 19 1 8 506 8 59 1896 42 22
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
[..1] days: 100.0 % 42 42 42
(7,30] days: 98.6 % 74 73 1 73
(30,360] days: 92.7 % 179 166 13 2 164
(360..) days: 94.7 % 3723 3526 197 3526
Function coverage date bins:
[..1] days: 100.0 % 8 8 8
(7,30] days: 100.0 % 5 5 5
(30,360] days: 100.0 % 1 1 1
(360..) days: 99.5 % 197 196 1 31 165
Branch coverage date bins:
[..1] days: 76.7 % 30 23 7 23
(7,30] days: 72.5 % 40 29 11 29
(30,360] days: 87.3 % 110 96 1 13 7 89
(360..) days: 76.2 % 2381 1815 1 8 493 8 1807 42 22

 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-2025, PostgreSQL Global Development Group
                                 15                 :                :  *
                                 16                 :                :  * IDENTIFICATION
                                 17                 :                :  *    src/backend/utils/adt/numeric.c
                                 18                 :                :  *
                                 19                 :                :  *-------------------------------------------------------------------------
                                 20                 :                :  */
                                 21                 :                : 
                                 22                 :                : #include "postgres.h"
                                 23                 :                : 
                                 24                 :                : #include <ctype.h>
                                 25                 :                : #include <float.h>
                                 26                 :                : #include <limits.h>
                                 27                 :                : #include <math.h>
                                 28                 :                : 
                                 29                 :                : #include "common/hashfn.h"
                                 30                 :                : #include "common/int.h"
                                 31                 :                : #include "common/int128.h"
                                 32                 :                : #include "funcapi.h"
                                 33                 :                : #include "lib/hyperloglog.h"
                                 34                 :                : #include "libpq/pqformat.h"
                                 35                 :                : #include "miscadmin.h"
                                 36                 :                : #include "nodes/nodeFuncs.h"
                                 37                 :                : #include "nodes/supportnodes.h"
                                 38                 :                : #include "optimizer/optimizer.h"
                                 39                 :                : #include "utils/array.h"
                                 40                 :                : #include "utils/builtins.h"
                                 41                 :                : #include "utils/float.h"
                                 42                 :                : #include "utils/guc.h"
                                 43                 :                : #include "utils/numeric.h"
                                 44                 :                : #include "utils/pg_lsn.h"
                                 45                 :                : #include "utils/sortsupport.h"
                                 46                 :                : 
                                 47                 :                : /* ----------
                                 48                 :                :  * Uncomment the following to enable compilation of dump_numeric()
                                 49                 :                :  * and dump_var() and to get a dump of any result produced by make_result().
                                 50                 :                :  * ----------
                                 51                 :                : #define NUMERIC_DEBUG
                                 52                 :                :  */
                                 53                 :                : 
                                 54                 :                : 
                                 55                 :                : /* ----------
                                 56                 :                :  * Local data types
                                 57                 :                :  *
                                 58                 :                :  * Numeric values are represented in a base-NBASE floating point format.
                                 59                 :                :  * Each "digit" ranges from 0 to NBASE-1.  The type NumericDigit is signed
                                 60                 :                :  * and wide enough to store a digit.  We assume that NBASE*NBASE can fit in
                                 61                 :                :  * an int.  Although the purely calculational routines could handle any even
                                 62                 :                :  * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
                                 63                 :                :  * in NBASE a power of ten, so that I/O conversions and decimal rounding
                                 64                 :                :  * are easy.  Also, it's actually more efficient if NBASE is rather less than
                                 65                 :                :  * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
                                 66                 :                :  * postpone processing carries.
                                 67                 :                :  *
                                 68                 :                :  * Values of NBASE other than 10000 are considered of historical interest only
                                 69                 :                :  * and are no longer supported in any sense; no mechanism exists for the client
                                 70                 :                :  * to discover the base, so every client supporting binary mode expects the
                                 71                 :                :  * base-10000 format.  If you plan to change this, also note the numeric
                                 72                 :                :  * abbreviation code, which assumes NBASE=10000.
                                 73                 :                :  * ----------
                                 74                 :                :  */
                                 75                 :                : 
                                 76                 :                : #if 0
                                 77                 :                : #define NBASE       10
                                 78                 :                : #define HALF_NBASE  5
                                 79                 :                : #define DEC_DIGITS  1           /* decimal digits per NBASE digit */
                                 80                 :                : #define MUL_GUARD_DIGITS    4   /* these are measured in NBASE digits */
                                 81                 :                : #define DIV_GUARD_DIGITS    8
                                 82                 :                : 
                                 83                 :                : typedef signed char NumericDigit;
                                 84                 :                : #endif
                                 85                 :                : 
                                 86                 :                : #if 0
                                 87                 :                : #define NBASE       100
                                 88                 :                : #define HALF_NBASE  50
                                 89                 :                : #define DEC_DIGITS  2           /* decimal digits per NBASE digit */
                                 90                 :                : #define MUL_GUARD_DIGITS    3   /* these are measured in NBASE digits */
                                 91                 :                : #define DIV_GUARD_DIGITS    6
                                 92                 :                : 
                                 93                 :                : typedef signed char NumericDigit;
                                 94                 :                : #endif
                                 95                 :                : 
                                 96                 :                : #if 1
                                 97                 :                : #define NBASE       10000
                                 98                 :                : #define HALF_NBASE  5000
                                 99                 :                : #define DEC_DIGITS  4           /* decimal digits per NBASE digit */
                                100                 :                : #define MUL_GUARD_DIGITS    2   /* these are measured in NBASE digits */
                                101                 :                : #define DIV_GUARD_DIGITS    4
                                102                 :                : 
                                103                 :                : typedef int16 NumericDigit;
                                104                 :                : #endif
                                105                 :                : 
                                106                 :                : #define NBASE_SQR   (NBASE * NBASE)
                                107                 :                : 
                                108                 :                : /*
                                109                 :                :  * The Numeric type as stored on disk.
                                110                 :                :  *
                                111                 :                :  * If the high bits of the first word of a NumericChoice (n_header, or
                                112                 :                :  * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
                                113                 :                :  * numeric follows the NumericShort format; if they are NUMERIC_POS or
                                114                 :                :  * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
                                115                 :                :  * the value is a NaN or Infinity.  We currently always store SPECIAL values
                                116                 :                :  * using just two bytes (i.e. only n_header), but previous releases used only
                                117                 :                :  * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
                                118                 :                :  * on disk if a database has been migrated using pg_upgrade.  In either case,
                                119                 :                :  * the low-order bits of a special value's header are reserved and currently
                                120                 :                :  * should always be set to zero.
                                121                 :                :  *
                                122                 :                :  * In the NumericShort format, the remaining 14 bits of the header word
                                123                 :                :  * (n_short.n_header) are allocated as follows: 1 for sign (positive or
                                124                 :                :  * negative), 6 for dynamic scale, and 7 for weight.  In practice, most
                                125                 :                :  * commonly-encountered values can be represented this way.
                                126                 :                :  *
                                127                 :                :  * In the NumericLong format, the remaining 14 bits of the header word
                                128                 :                :  * (n_long.n_sign_dscale) represent the display scale; and the weight is
                                129                 :                :  * stored separately in n_weight.
                                130                 :                :  *
                                131                 :                :  * NOTE: by convention, values in the packed form have been stripped of
                                132                 :                :  * all leading and trailing zero digits (where a "digit" is of base NBASE).
                                133                 :                :  * In particular, if the value is zero, there will be no digits at all!
                                134                 :                :  * The weight is arbitrary in that case, but we normally set it to zero.
                                135                 :                :  */
                                136                 :                : 
                                137                 :                : struct NumericShort
                                138                 :                : {
                                139                 :                :     uint16      n_header;       /* Sign + display scale + weight */
                                140                 :                :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
                                141                 :                : };
                                142                 :                : 
                                143                 :                : struct NumericLong
                                144                 :                : {
                                145                 :                :     uint16      n_sign_dscale;  /* Sign + display scale */
                                146                 :                :     int16       n_weight;       /* Weight of 1st digit  */
                                147                 :                :     NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
                                148                 :                : };
                                149                 :                : 
                                150                 :                : union NumericChoice
                                151                 :                : {
                                152                 :                :     uint16      n_header;       /* Header word */
                                153                 :                :     struct NumericLong n_long;  /* Long form (4-byte header) */
                                154                 :                :     struct NumericShort n_short;    /* Short form (2-byte header) */
                                155                 :                : };
                                156                 :                : 
                                157                 :                : struct NumericData
                                158                 :                : {
                                159                 :                :     int32       vl_len_;        /* varlena header (do not touch directly!) */
                                160                 :                :     union NumericChoice choice; /* choice of format */
                                161                 :                : };
                                162                 :                : 
                                163                 :                : 
                                164                 :                : /*
                                165                 :                :  * Interpretation of high bits.
                                166                 :                :  */
                                167                 :                : 
                                168                 :                : #define NUMERIC_SIGN_MASK   0xC000
                                169                 :                : #define NUMERIC_POS         0x0000
                                170                 :                : #define NUMERIC_NEG         0x4000
                                171                 :                : #define NUMERIC_SHORT       0x8000
                                172                 :                : #define NUMERIC_SPECIAL     0xC000
                                173                 :                : 
                                174                 :                : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
                                175                 :                : #define NUMERIC_IS_SHORT(n)     (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
                                176                 :                : #define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
                                177                 :                : 
                                178                 :                : #define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
                                179                 :                : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
                                180                 :                : 
                                181                 :                : /*
                                182                 :                :  * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
                                183                 :                :  * header; otherwise, we want the long one.  Instead of testing against each
                                184                 :                :  * value, we can just look at the high bit, for a slight efficiency gain.
                                185                 :                :  */
                                186                 :                : #define NUMERIC_HEADER_IS_SHORT(n)  (((n)->choice.n_header & 0x8000) != 0)
                                187                 :                : #define NUMERIC_HEADER_SIZE(n) \
                                188                 :                :     (VARHDRSZ + sizeof(uint16) + \
                                189                 :                :      (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
                                190                 :                : 
                                191                 :                : /*
                                192                 :                :  * Definitions for special values (NaN, positive infinity, negative infinity).
                                193                 :                :  *
                                194                 :                :  * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
                                195                 :                :  * infinity, 11 for negative infinity.  (This makes the sign bit match where
                                196                 :                :  * it is in a short-format value, though we make no use of that at present.)
                                197                 :                :  * We could mask off the remaining bits before testing the active bits, but
                                198                 :                :  * currently those bits must be zeroes, so masking would just add cycles.
                                199                 :                :  */
                                200                 :                : #define NUMERIC_EXT_SIGN_MASK   0xF000  /* high bits plus NaN/Inf flag bits */
                                201                 :                : #define NUMERIC_NAN             0xC000
                                202                 :                : #define NUMERIC_PINF            0xD000
                                203                 :                : #define NUMERIC_NINF            0xF000
                                204                 :                : #define NUMERIC_INF_SIGN_MASK   0x2000
                                205                 :                : 
                                206                 :                : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
                                207                 :                : #define NUMERIC_IS_NAN(n)       ((n)->choice.n_header == NUMERIC_NAN)
                                208                 :                : #define NUMERIC_IS_PINF(n)      ((n)->choice.n_header == NUMERIC_PINF)
                                209                 :                : #define NUMERIC_IS_NINF(n)      ((n)->choice.n_header == NUMERIC_NINF)
                                210                 :                : #define NUMERIC_IS_INF(n) \
                                211                 :                :     (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
                                212                 :                : 
                                213                 :                : /*
                                214                 :                :  * Short format definitions.
                                215                 :                :  */
                                216                 :                : 
                                217                 :                : #define NUMERIC_SHORT_SIGN_MASK         0x2000
                                218                 :                : #define NUMERIC_SHORT_DSCALE_MASK       0x1F80
                                219                 :                : #define NUMERIC_SHORT_DSCALE_SHIFT      7
                                220                 :                : #define NUMERIC_SHORT_DSCALE_MAX        \
                                221                 :                :     (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
                                222                 :                : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK  0x0040
                                223                 :                : #define NUMERIC_SHORT_WEIGHT_MASK       0x003F
                                224                 :                : #define NUMERIC_SHORT_WEIGHT_MAX        NUMERIC_SHORT_WEIGHT_MASK
                                225                 :                : #define NUMERIC_SHORT_WEIGHT_MIN        (-(NUMERIC_SHORT_WEIGHT_MASK+1))
                                226                 :                : 
                                227                 :                : /*
                                228                 :                :  * Extract sign, display scale, weight.  These macros extract field values
                                229                 :                :  * suitable for the NumericVar format from the Numeric (on-disk) format.
                                230                 :                :  *
                                231                 :                :  * Note that we don't trouble to ensure that dscale and weight read as zero
                                232                 :                :  * for an infinity; however, that doesn't matter since we never convert
                                233                 :                :  * "special" numerics to NumericVar form.  Only the constants defined below
                                234                 :                :  * (const_nan, etc) ever represent a non-finite value as a NumericVar.
                                235                 :                :  */
                                236                 :                : 
                                237                 :                : #define NUMERIC_DSCALE_MASK         0x3FFF
                                238                 :                : #define NUMERIC_DSCALE_MAX          NUMERIC_DSCALE_MASK
                                239                 :                : 
                                240                 :                : #define NUMERIC_SIGN(n) \
                                241                 :                :     (NUMERIC_IS_SHORT(n) ? \
                                242                 :                :         (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
                                243                 :                :          NUMERIC_NEG : NUMERIC_POS) : \
                                244                 :                :         (NUMERIC_IS_SPECIAL(n) ? \
                                245                 :                :          NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
                                246                 :                : #define NUMERIC_DSCALE(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
                                247                 :                :     ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
                                248                 :                :         >> NUMERIC_SHORT_DSCALE_SHIFT \
                                249                 :                :     : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
                                250                 :                : #define NUMERIC_WEIGHT(n)   (NUMERIC_HEADER_IS_SHORT((n)) ? \
                                251                 :                :     (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
                                252                 :                :         ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
                                253                 :                :      | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
                                254                 :                :     : ((n)->choice.n_long.n_weight))
                                255                 :                : 
                                256                 :                : /*
                                257                 :                :  * Maximum weight of a stored Numeric value (based on the use of int16 for the
                                258                 :                :  * weight in NumericLong).  Note that intermediate values held in NumericVar
                                259                 :                :  * and NumericSumAccum variables may have much larger weights.
                                260                 :                :  */
                                261                 :                : #define NUMERIC_WEIGHT_MAX          PG_INT16_MAX
                                262                 :                : 
                                263                 :                : /* ----------
                                264                 :                :  * NumericVar is the format we use for arithmetic.  The digit-array part
                                265                 :                :  * is the same as the NumericData storage format, but the header is more
                                266                 :                :  * complex.
                                267                 :                :  *
                                268                 :                :  * The value represented by a NumericVar is determined by the sign, weight,
                                269                 :                :  * ndigits, and digits[] array.  If it is a "special" value (NaN or Inf)
                                270                 :                :  * then only the sign field matters; ndigits should be zero, and the weight
                                271                 :                :  * and dscale fields are ignored.
                                272                 :                :  *
                                273                 :                :  * Note: the first digit of a NumericVar's value is assumed to be multiplied
                                274                 :                :  * by NBASE ** weight.  Another way to say it is that there are weight+1
                                275                 :                :  * digits before the decimal point.  It is possible to have weight < 0.
                                276                 :                :  *
                                277                 :                :  * buf points at the physical start of the palloc'd digit buffer for the
                                278                 :                :  * NumericVar.  digits points at the first digit in actual use (the one
                                279                 :                :  * with the specified weight).  We normally leave an unused digit or two
                                280                 :                :  * (preset to zeroes) between buf and digits, so that there is room to store
                                281                 :                :  * a carry out of the top digit without reallocating space.  We just need to
                                282                 :                :  * decrement digits (and increment weight) to make room for the carry digit.
                                283                 :                :  * (There is no such extra space in a numeric value stored in the database,
                                284                 :                :  * only in a NumericVar in memory.)
                                285                 :                :  *
                                286                 :                :  * If buf is NULL then the digit buffer isn't actually palloc'd and should
                                287                 :                :  * not be freed --- see the constants below for an example.
                                288                 :                :  *
                                289                 :                :  * dscale, or display scale, is the nominal precision expressed as number
                                290                 :                :  * of digits after the decimal point (it must always be >= 0 at present).
                                291                 :                :  * dscale may be more than the number of physically stored fractional digits,
                                292                 :                :  * implying that we have suppressed storage of significant trailing zeroes.
                                293                 :                :  * It should never be less than the number of stored digits, since that would
                                294                 :                :  * imply hiding digits that are present.  NOTE that dscale is always expressed
                                295                 :                :  * in *decimal* digits, and so it may correspond to a fractional number of
                                296                 :                :  * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
                                297                 :                :  *
                                298                 :                :  * rscale, or result scale, is the target precision for a computation.
                                299                 :                :  * Like dscale it is expressed as number of *decimal* digits after the decimal
                                300                 :                :  * point, and is always >= 0 at present.
                                301                 :                :  * Note that rscale is not stored in variables --- it's figured on-the-fly
                                302                 :                :  * from the dscales of the inputs.
                                303                 :                :  *
                                304                 :                :  * While we consistently use "weight" to refer to the base-NBASE weight of
                                305                 :                :  * a numeric value, it is convenient in some scale-related calculations to
                                306                 :                :  * make use of the base-10 weight (ie, the approximate log10 of the value).
                                307                 :                :  * To avoid confusion, such a decimal-units weight is called a "dweight".
                                308                 :                :  *
                                309                 :                :  * NB: All the variable-level functions are written in a style that makes it
                                310                 :                :  * possible to give one and the same variable as argument and destination.
                                311                 :                :  * This is feasible because the digit buffer is separate from the variable.
                                312                 :                :  * ----------
                                313                 :                :  */
                                314                 :                : typedef struct NumericVar
                                315                 :                : {
                                316                 :                :     int         ndigits;        /* # of digits in digits[] - can be 0! */
                                317                 :                :     int         weight;         /* weight of first digit */
                                318                 :                :     int         sign;           /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
                                319                 :                :     int         dscale;         /* display scale */
                                320                 :                :     NumericDigit *buf;          /* start of palloc'd space for digits[] */
                                321                 :                :     NumericDigit *digits;       /* base-NBASE digits */
                                322                 :                : } NumericVar;
                                323                 :                : 
                                324                 :                : 
                                325                 :                : /* ----------
                                326                 :                :  * Data for generate_series
                                327                 :                :  * ----------
                                328                 :                :  */
                                329                 :                : typedef struct
                                330                 :                : {
                                331                 :                :     NumericVar  current;
                                332                 :                :     NumericVar  stop;
                                333                 :                :     NumericVar  step;
                                334                 :                : } generate_series_numeric_fctx;
                                335                 :                : 
                                336                 :                : 
                                337                 :                : /* ----------
                                338                 :                :  * Sort support.
                                339                 :                :  * ----------
                                340                 :                :  */
                                341                 :                : typedef struct
                                342                 :                : {
                                343                 :                :     void       *buf;            /* buffer for short varlenas */
                                344                 :                :     int64       input_count;    /* number of non-null values seen */
                                345                 :                :     bool        estimating;     /* true if estimating cardinality */
                                346                 :                : 
                                347                 :                :     hyperLogLogState abbr_card; /* cardinality estimator */
                                348                 :                : } NumericSortSupport;
                                349                 :                : 
                                350                 :                : 
                                351                 :                : /* ----------
                                352                 :                :  * Fast sum accumulator.
                                353                 :                :  *
                                354                 :                :  * NumericSumAccum is used to implement SUM(), and other standard aggregates
                                355                 :                :  * that track the sum of input values.  It uses 32-bit integers to store the
                                356                 :                :  * digits, instead of the normal 16-bit integers (with NBASE=10000).  This
                                357                 :                :  * way, we can safely accumulate up to NBASE - 1 values without propagating
                                358                 :                :  * carry, before risking overflow of any of the digits.  'num_uncarried'
                                359                 :                :  * tracks how many values have been accumulated without propagating carry.
                                360                 :                :  *
                                361                 :                :  * Positive and negative values are accumulated separately, in 'pos_digits'
                                362                 :                :  * and 'neg_digits'.  This is simpler and faster than deciding whether to add
                                363                 :                :  * or subtract from the current value, for each new value (see sub_var() for
                                364                 :                :  * the logic we avoid by doing this).  Both buffers are of same size, and
                                365                 :                :  * have the same weight and scale.  In accum_sum_final(), the positive and
                                366                 :                :  * negative sums are added together to produce the final result.
                                367                 :                :  *
                                368                 :                :  * When a new value has a larger ndigits or weight than the accumulator
                                369                 :                :  * currently does, the accumulator is enlarged to accommodate the new value.
                                370                 :                :  * We normally have one zero digit reserved for carry propagation, and that
                                371                 :                :  * is indicated by the 'have_carry_space' flag.  When accum_sum_carry() uses
                                372                 :                :  * up the reserved digit, it clears the 'have_carry_space' flag.  The next
                                373                 :                :  * call to accum_sum_add() will enlarge the buffer, to make room for the
                                374                 :                :  * extra digit, and set the flag again.
                                375                 :                :  *
                                376                 :                :  * To initialize a new accumulator, simply reset all fields to zeros.
                                377                 :                :  *
                                378                 :                :  * The accumulator does not handle NaNs.
                                379                 :                :  * ----------
                                380                 :                :  */
                                381                 :                : typedef struct NumericSumAccum
                                382                 :                : {
                                383                 :                :     int         ndigits;
                                384                 :                :     int         weight;
                                385                 :                :     int         dscale;
                                386                 :                :     int         num_uncarried;
                                387                 :                :     bool        have_carry_space;
                                388                 :                :     int32      *pos_digits;
                                389                 :                :     int32      *neg_digits;
                                390                 :                : } NumericSumAccum;
                                391                 :                : 
                                392                 :                : 
                                393                 :                : /*
                                394                 :                :  * We define our own macros for packing and unpacking abbreviated-key
                                395                 :                :  * representations, just to have a notational indication that that's
                                396                 :                :  * what we're doing.  Now that sizeof(Datum) is always 8, we can rely
                                397                 :                :  * on fitting an int64 into Datum.
                                398                 :                :  *
                                399                 :                :  * The range of abbreviations for finite values is from +PG_INT64_MAX
                                400                 :                :  * to -PG_INT64_MAX.  NaN has the abbreviation PG_INT64_MIN, and we
                                401                 :                :  * define the sort ordering to make that work out properly (see further
                                402                 :                :  * comments below).  PINF and NINF share the abbreviations of the largest
                                403                 :                :  * and smallest finite abbreviation classes.
                                404                 :                :  */
                                405                 :                : #define NumericAbbrevGetDatum(X) Int64GetDatum(X)
                                406                 :                : #define DatumGetNumericAbbrev(X) DatumGetInt64(X)
                                407                 :                : #define NUMERIC_ABBREV_NAN       NumericAbbrevGetDatum(PG_INT64_MIN)
                                408                 :                : #define NUMERIC_ABBREV_PINF      NumericAbbrevGetDatum(-PG_INT64_MAX)
                                409                 :                : #define NUMERIC_ABBREV_NINF      NumericAbbrevGetDatum(PG_INT64_MAX)
                                410                 :                : 
                                411                 :                : 
                                412                 :                : /* ----------
                                413                 :                :  * Some preinitialized constants
                                414                 :                :  * ----------
                                415                 :                :  */
                                416                 :                : static const NumericDigit const_zero_data[1] = {0};
                                417                 :                : static const NumericVar const_zero =
                                418                 :                : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
                                419                 :                : 
                                420                 :                : static const NumericDigit const_one_data[1] = {1};
                                421                 :                : static const NumericVar const_one =
                                422                 :                : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
                                423                 :                : 
                                424                 :                : static const NumericVar const_minus_one =
                                425                 :                : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
                                426                 :                : 
                                427                 :                : static const NumericDigit const_two_data[1] = {2};
                                428                 :                : static const NumericVar const_two =
                                429                 :                : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
                                430                 :                : 
                                431                 :                : #if DEC_DIGITS == 4
                                432                 :                : static const NumericDigit const_zero_point_nine_data[1] = {9000};
                                433                 :                : #elif DEC_DIGITS == 2
                                434                 :                : static const NumericDigit const_zero_point_nine_data[1] = {90};
                                435                 :                : #elif DEC_DIGITS == 1
                                436                 :                : static const NumericDigit const_zero_point_nine_data[1] = {9};
                                437                 :                : #endif
                                438                 :                : static const NumericVar const_zero_point_nine =
                                439                 :                : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
                                440                 :                : 
                                441                 :                : #if DEC_DIGITS == 4
                                442                 :                : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
                                443                 :                : #elif DEC_DIGITS == 2
                                444                 :                : static const NumericDigit const_one_point_one_data[2] = {1, 10};
                                445                 :                : #elif DEC_DIGITS == 1
                                446                 :                : static const NumericDigit const_one_point_one_data[2] = {1, 1};
                                447                 :                : #endif
                                448                 :                : static const NumericVar const_one_point_one =
                                449                 :                : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
                                450                 :                : 
                                451                 :                : static const NumericVar const_nan =
                                452                 :                : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
                                453                 :                : 
                                454                 :                : static const NumericVar const_pinf =
                                455                 :                : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
                                456                 :                : 
                                457                 :                : static const NumericVar const_ninf =
                                458                 :                : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
                                459                 :                : 
                                460                 :                : #if DEC_DIGITS == 4
                                461                 :                : static const int round_powers[4] = {0, 1000, 100, 10};
                                462                 :                : #endif
                                463                 :                : 
                                464                 :                : 
                                465                 :                : /* ----------
                                466                 :                :  * Local functions
                                467                 :                :  * ----------
                                468                 :                :  */
                                469                 :                : 
                                470                 :                : #ifdef NUMERIC_DEBUG
                                471                 :                : static void dump_numeric(const char *str, Numeric num);
                                472                 :                : static void dump_var(const char *str, NumericVar *var);
                                473                 :                : #else
                                474                 :                : #define dump_numeric(s,n)
                                475                 :                : #define dump_var(s,v)
                                476                 :                : #endif
                                477                 :                : 
                                478                 :                : #define digitbuf_alloc(ndigits)  \
                                479                 :                :     ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
                                480                 :                : #define digitbuf_free(buf)  \
                                481                 :                :     do { \
                                482                 :                :          if ((buf) != NULL) \
                                483                 :                :              pfree(buf); \
                                484                 :                :     } while (0)
                                485                 :                : 
                                486                 :                : #define init_var(v)     memset(v, 0, sizeof(NumericVar))
                                487                 :                : 
                                488                 :                : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
                                489                 :                :     (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
                                490                 :                : #define NUMERIC_NDIGITS(num) \
                                491                 :                :     ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
                                492                 :                : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
                                493                 :                :     ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
                                494                 :                :     (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
                                495                 :                :     (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
                                496                 :                : 
                                497                 :                : static void alloc_var(NumericVar *var, int ndigits);
                                498                 :                : static void free_var(NumericVar *var);
                                499                 :                : static void zero_var(NumericVar *var);
                                500                 :                : 
                                501                 :                : static bool set_var_from_str(const char *str, const char *cp,
                                502                 :                :                              NumericVar *dest, const char **endptr,
                                503                 :                :                              Node *escontext);
                                504                 :                : static bool set_var_from_non_decimal_integer_str(const char *str,
                                505                 :                :                                                  const char *cp, int sign,
                                506                 :                :                                                  int base, NumericVar *dest,
                                507                 :                :                                                  const char **endptr,
                                508                 :                :                                                  Node *escontext);
                                509                 :                : static void set_var_from_num(Numeric num, NumericVar *dest);
                                510                 :                : static void init_var_from_num(Numeric num, NumericVar *dest);
                                511                 :                : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
                                512                 :                : static char *get_str_from_var(const NumericVar *var);
                                513                 :                : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
                                514                 :                : 
                                515                 :                : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
                                516                 :                : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
                                517                 :                : 
                                518                 :                : static Numeric duplicate_numeric(Numeric num);
                                519                 :                : static Numeric make_result(const NumericVar *var);
                                520                 :                : static Numeric make_result_safe(const NumericVar *var, Node *escontext);
                                521                 :                : 
                                522                 :                : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
                                523                 :                : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
                                524                 :                : 
                                525                 :                : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
                                526                 :                : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
                                527                 :                : static void int64_to_numericvar(int64 val, NumericVar *var);
                                528                 :                : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
                                529                 :                : static void int128_to_numericvar(INT128 val, NumericVar *var);
                                530                 :                : static double numericvar_to_double_no_overflow(const NumericVar *var);
                                531                 :                : 
                                532                 :                : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
                                533                 :                : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
                                534                 :                : static int  numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
                                535                 :                : static int  numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
                                536                 :                : 
                                537                 :                : static Datum numeric_abbrev_convert_var(const NumericVar *var,
                                538                 :                :                                         NumericSortSupport *nss);
                                539                 :                : 
                                540                 :                : static int  cmp_numerics(Numeric num1, Numeric num2);
                                541                 :                : static int  cmp_var(const NumericVar *var1, const NumericVar *var2);
                                542                 :                : static int  cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
                                543                 :                :                            int var1weight, int var1sign,
                                544                 :                :                            const NumericDigit *var2digits, int var2ndigits,
                                545                 :                :                            int var2weight, int var2sign);
                                546                 :                : static void add_var(const NumericVar *var1, const NumericVar *var2,
                                547                 :                :                     NumericVar *result);
                                548                 :                : static void sub_var(const NumericVar *var1, const NumericVar *var2,
                                549                 :                :                     NumericVar *result);
                                550                 :                : static void mul_var(const NumericVar *var1, const NumericVar *var2,
                                551                 :                :                     NumericVar *result,
                                552                 :                :                     int rscale);
                                553                 :                : static void mul_var_short(const NumericVar *var1, const NumericVar *var2,
                                554                 :                :                           NumericVar *result);
                                555                 :                : static void div_var(const NumericVar *var1, const NumericVar *var2,
                                556                 :                :                     NumericVar *result, int rscale, bool round, bool exact);
                                557                 :                : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
                                558                 :                :                         NumericVar *result, int rscale, bool round);
                                559                 :                : #ifdef HAVE_INT128
                                560                 :                : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
                                561                 :                :                           NumericVar *result, int rscale, bool round);
                                562                 :                : #endif
                                563                 :                : static int  select_div_scale(const NumericVar *var1, const NumericVar *var2);
                                564                 :                : static void mod_var(const NumericVar *var1, const NumericVar *var2,
                                565                 :                :                     NumericVar *result);
                                566                 :                : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
                                567                 :                :                         NumericVar *quot, NumericVar *rem);
                                568                 :                : static void ceil_var(const NumericVar *var, NumericVar *result);
                                569                 :                : static void floor_var(const NumericVar *var, NumericVar *result);
                                570                 :                : 
                                571                 :                : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
                                572                 :                :                     NumericVar *result);
                                573                 :                : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
                                574                 :                : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
                                575                 :                : static int  estimate_ln_dweight(const NumericVar *var);
                                576                 :                : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
                                577                 :                : static void log_var(const NumericVar *base, const NumericVar *num,
                                578                 :                :                     NumericVar *result);
                                579                 :                : static void power_var(const NumericVar *base, const NumericVar *exp,
                                580                 :                :                       NumericVar *result);
                                581                 :                : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
                                582                 :                :                           NumericVar *result);
                                583                 :                : static void power_ten_int(int exp, NumericVar *result);
                                584                 :                : static void random_var(pg_prng_state *state, const NumericVar *rmin,
                                585                 :                :                        const NumericVar *rmax, NumericVar *result);
                                586                 :                : 
                                587                 :                : static int  cmp_abs(const NumericVar *var1, const NumericVar *var2);
                                588                 :                : static int  cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
                                589                 :                :                            int var1weight,
                                590                 :                :                            const NumericDigit *var2digits, int var2ndigits,
                                591                 :                :                            int var2weight);
                                592                 :                : static void add_abs(const NumericVar *var1, const NumericVar *var2,
                                593                 :                :                     NumericVar *result);
                                594                 :                : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
                                595                 :                :                     NumericVar *result);
                                596                 :                : static void round_var(NumericVar *var, int rscale);
                                597                 :                : static void trunc_var(NumericVar *var, int rscale);
                                598                 :                : static void strip_var(NumericVar *var);
                                599                 :                : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
                                600                 :                :                            const NumericVar *count_var,
                                601                 :                :                            NumericVar *result_var);
                                602                 :                : 
                                603                 :                : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
                                604                 :                : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
                                605                 :                : static void accum_sum_carry(NumericSumAccum *accum);
                                606                 :                : static void accum_sum_reset(NumericSumAccum *accum);
                                607                 :                : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
                                608                 :                : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
                                609                 :                : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
                                610                 :                : 
                                611                 :                : 
                                612                 :                : /* ----------------------------------------------------------------------
                                613                 :                :  *
                                614                 :                :  * Input-, output- and rounding-functions
                                615                 :                :  *
                                616                 :                :  * ----------------------------------------------------------------------
                                617                 :                :  */
                                618                 :                : 
                                619                 :                : 
                                620                 :                : /*
                                621                 :                :  * numeric_in() -
                                622                 :                :  *
                                623                 :                :  *  Input function for numeric data type
                                624                 :                :  */
                                625                 :                : Datum
 9216 tgl@sss.pgh.pa.us         626                 :CBC       81939 : numeric_in(PG_FUNCTION_ARGS)
                                627                 :                : {
                                628                 :          81939 :     char       *str = PG_GETARG_CSTRING(0);
                                629                 :                : #ifdef NOT_USED
                                630                 :                :     Oid         typelem = PG_GETARG_OID(1);
                                631                 :                : #endif
                                632                 :          81939 :     int32       typmod = PG_GETARG_INT32(2);
 1002                           633                 :          81939 :     Node       *escontext = fcinfo->context;
                                634                 :                :     Numeric     res;
                                635                 :                :     const char *cp;
                                636                 :                :     const char *numstart;
                                637                 :                :     int         sign;
                                638                 :                : 
                                639                 :                :     /* Skip leading spaces */
 5995                           640                 :          81939 :     cp = str;
                                641         [ +  + ]:          94149 :     while (*cp)
                                642                 :                :     {
                                643         [ +  + ]:          94140 :         if (!isspace((unsigned char) *cp))
                                644                 :          81930 :             break;
                                645                 :          12210 :         cp++;
                                646                 :                :     }
                                647                 :                : 
                                648                 :                :     /*
                                649                 :                :      * Process the number's sign. This duplicates logic in set_var_from_str(),
                                650                 :                :      * but it's worth doing here, since it simplifies the handling of
                                651                 :                :      * infinities and non-decimal integers.
                                652                 :                :      */
  957 dean.a.rasheed@gmail      653                 :          81939 :     numstart = cp;
                                654                 :          81939 :     sign = NUMERIC_POS;
                                655                 :                : 
                                656         [ +  + ]:          81939 :     if (*cp == '+')
                                657                 :             24 :         cp++;
                                658         [ +  + ]:          81915 :     else if (*cp == '-')
                                659                 :                :     {
                                660                 :           2063 :         sign = NUMERIC_NEG;
                                661                 :           2063 :         cp++;
                                662                 :                :     }
                                663                 :                : 
                                664                 :                :     /*
                                665                 :                :      * Check for NaN and infinities.  We recognize the same strings allowed by
                                666                 :                :      * float8in().
                                667                 :                :      *
                                668                 :                :      * Since all other legal inputs have a digit or a decimal point after the
                                669                 :                :      * sign, we need only check for NaN/infinity if that's not the case.
                                670                 :                :      */
                                671   [ +  +  +  + ]:          81939 :     if (!isdigit((unsigned char) *cp) && *cp != '.')
                                672                 :                :     {
                                673                 :                :         /*
                                674                 :                :          * The number must be NaN or infinity; anything else can only be a
                                675                 :                :          * syntax error. Note that NaN mustn't have a sign.
                                676                 :                :          */
                                677         [ +  + ]:            894 :         if (pg_strncasecmp(numstart, "NaN", 3) == 0)
                                678                 :                :         {
                                679                 :            299 :             res = make_result(&const_nan);
                                680                 :            299 :             cp = numstart + 3;
                                681                 :                :         }
                                682         [ +  + ]:            595 :         else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
                                683                 :                :         {
                                684         [ +  + ]:            246 :             res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
                                685                 :            246 :             cp += 8;
                                686                 :                :         }
                                687         [ +  + ]:            349 :         else if (pg_strncasecmp(cp, "inf", 3) == 0)
                                688                 :                :         {
                                689         [ +  + ]:            294 :             res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
                                690                 :            294 :             cp += 3;
                                691                 :                :         }
                                692                 :                :         else
                                693                 :             55 :             goto invalid_syntax;
                                694                 :                : 
                                695                 :                :         /*
                                696                 :                :          * Check for trailing junk; there should be nothing left but spaces.
                                697                 :                :          *
                                698                 :                :          * We intentionally do this check before applying the typmod because
                                699                 :                :          * we would like to throw any trailing-junk syntax error before any
                                700                 :                :          * semantic error resulting from apply_typmod_special().
                                701                 :                :          */
                                702         [ +  + ]:            860 :         while (*cp)
                                703                 :                :         {
                                704         [ -  + ]:             21 :             if (!isspace((unsigned char) *cp))
  957 dean.a.rasheed@gmail      705                 :UBC           0 :                 goto invalid_syntax;
  957 dean.a.rasheed@gmail      706                 :CBC          21 :             cp++;
                                707                 :                :         }
                                708                 :                : 
                                709         [ -  + ]:            839 :         if (!apply_typmod_special(res, typmod, escontext))
  957 dean.a.rasheed@gmail      710                 :UBC           0 :             PG_RETURN_NULL();
                                711                 :                :     }
                                712                 :                :     else
                                713                 :                :     {
                                714                 :                :         /*
                                715                 :                :          * We have a normal numeric value, which may be a non-decimal integer
                                716                 :                :          * or a regular decimal number.
                                717                 :                :          */
                                718                 :                :         NumericVar  value;
                                719                 :                :         int         base;
                                720                 :                : 
 5995 tgl@sss.pgh.pa.us         721                 :CBC       81045 :         init_var(&value);
                                722                 :                : 
                                723                 :                :         /*
                                724                 :                :          * Determine the number's base by looking for a non-decimal prefix
                                725                 :                :          * indicator ("0x", "0o", or "0b").
                                726                 :                :          */
  957 dean.a.rasheed@gmail      727         [ +  + ]:          81045 :         if (cp[0] == '0')
                                728                 :                :         {
                                729   [ +  +  +  + ]:          24692 :             switch (cp[1])
                                730                 :                :             {
                                731                 :             36 :                 case 'x':
                                732                 :                :                 case 'X':
                                733                 :             36 :                     base = 16;
                                734                 :             36 :                     break;
                                735                 :             21 :                 case 'o':
                                736                 :                :                 case 'O':
                                737                 :             21 :                     base = 8;
                                738                 :             21 :                     break;
                                739                 :             21 :                 case 'b':
                                740                 :                :                 case 'B':
                                741                 :             21 :                     base = 2;
                                742                 :             21 :                     break;
                                743                 :          24614 :                 default:
                                744                 :          24614 :                     base = 10;
                                745                 :                :             }
                                746                 :                :         }
                                747                 :                :         else
                                748                 :          56353 :             base = 10;
                                749                 :                : 
                                750                 :                :         /* Parse the rest of the number and apply the sign */
                                751         [ +  + ]:          81045 :         if (base == 10)
                                752                 :                :         {
                                753         [ -  + ]:          80967 :             if (!set_var_from_str(str, cp, &value, &cp, escontext))
                                754                 :             12 :                 PG_RETURN_NULL();
                                755                 :          80943 :             value.sign = sign;
                                756                 :                :         }
                                757                 :                :         else
                                758                 :                :         {
                                759         [ -  + ]:             78 :             if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
                                760                 :                :                                                       &value, &cp, escontext))
  957 dean.a.rasheed@gmail      761                 :UBC           0 :                 PG_RETURN_NULL();
                                762                 :                :         }
                                763                 :                : 
                                764                 :                :         /*
                                765                 :                :          * Should be nothing left but spaces. As above, throw any typmod error
                                766                 :                :          * after finishing syntax check.
                                767                 :                :          */
 5995 tgl@sss.pgh.pa.us         768         [ +  + ]:CBC       81051 :         while (*cp)
                                769                 :                :         {
                                770         [ +  + ]:             75 :             if (!isspace((unsigned char) *cp))
  957 dean.a.rasheed@gmail      771                 :             36 :                 goto invalid_syntax;
 5995 tgl@sss.pgh.pa.us         772                 :             39 :             cp++;
                                773                 :                :         }
                                774                 :                : 
 1002                           775         [ +  + ]:          80976 :         if (!apply_typmod(&value, typmod, escontext))
                                776                 :             12 :             PG_RETURN_NULL();
                                777                 :                : 
    1 michael@paquier.xyz       778                 :GNC       80964 :         res = make_result_safe(&value, escontext);
                                779                 :                : 
 5995 tgl@sss.pgh.pa.us         780                 :CBC       80964 :         free_var(&value);
                                781                 :                :     }
                                782                 :                : 
 9216                           783                 :          81803 :     PG_RETURN_NUMERIC(res);
                                784                 :                : 
  957 dean.a.rasheed@gmail      785                 :             91 : invalid_syntax:
                                786         [ +  + ]:             91 :     ereturn(escontext, (Datum) 0,
                                787                 :                :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                                788                 :                :              errmsg("invalid input syntax for type %s: \"%s\"",
                                789                 :                :                     "numeric", str)));
                                790                 :                : }
                                791                 :                : 
                                792                 :                : 
                                793                 :                : /*
                                794                 :                :  * numeric_out() -
                                795                 :                :  *
                                796                 :                :  *  Output function for numeric data type
                                797                 :                :  */
                                798                 :                : Datum
 9216 tgl@sss.pgh.pa.us         799                 :         426306 : numeric_out(PG_FUNCTION_ARGS)
                                800                 :                : {
                                801                 :         426306 :     Numeric     num = PG_GETARG_NUMERIC(0);
                                802                 :                :     NumericVar  x;
                                803                 :                :     char       *str;
                                804                 :                : 
                                805                 :                :     /*
                                806                 :                :      * Handle NaN and infinities
                                807                 :                :      */
 1872                           808         [ +  + ]:         426306 :     if (NUMERIC_IS_SPECIAL(num))
                                809                 :                :     {
                                810         [ +  + ]:           1794 :         if (NUMERIC_IS_PINF(num))
                                811                 :            520 :             PG_RETURN_CSTRING(pstrdup("Infinity"));
                                812         [ +  + ]:           1274 :         else if (NUMERIC_IS_NINF(num))
                                813                 :            329 :             PG_RETURN_CSTRING(pstrdup("-Infinity"));
                                814                 :                :         else
                                815                 :            945 :             PG_RETURN_CSTRING(pstrdup("NaN"));
                                816                 :                :     }
                                817                 :                : 
                                818                 :                :     /*
                                819                 :                :      * Get the number in the variable format.
                                820                 :                :      */
 4672 heikki.linnakangas@i      821                 :         424512 :     init_var_from_num(num, &x);
                                822                 :                : 
                                823                 :         424512 :     str = get_str_from_var(&x);
                                824                 :                : 
 9216 tgl@sss.pgh.pa.us         825                 :         424512 :     PG_RETURN_CSTRING(str);
                                826                 :                : }
                                827                 :                : 
                                828                 :                : /*
                                829                 :                :  * numeric_is_nan() -
                                830                 :                :  *
                                831                 :                :  *  Is Numeric value a NaN?
                                832                 :                :  */
                                833                 :                : bool
 5517 rhaas@postgresql.org      834                 :           3731 : numeric_is_nan(Numeric num)
                                835                 :                : {
                                836                 :           3731 :     return NUMERIC_IS_NAN(num);
                                837                 :                : }
                                838                 :                : 
                                839                 :                : /*
                                840                 :                :  * numeric_is_inf() -
                                841                 :                :  *
                                842                 :                :  *  Is Numeric value an infinity?
                                843                 :                :  */
                                844                 :                : bool
 1872 tgl@sss.pgh.pa.us         845                 :            156 : numeric_is_inf(Numeric num)
                                846                 :                : {
                                847                 :            156 :     return NUMERIC_IS_INF(num);
                                848                 :                : }
                                849                 :                : 
                                850                 :                : /*
                                851                 :                :  * numeric_is_integral() -
                                852                 :                :  *
                                853                 :                :  *  Is Numeric value integral?
                                854                 :                :  */
                                855                 :                : static bool
                                856                 :             33 : numeric_is_integral(Numeric num)
                                857                 :                : {
                                858                 :                :     NumericVar  arg;
                                859                 :                : 
                                860                 :                :     /* Reject NaN, but infinities are considered integral */
                                861         [ +  + ]:             33 :     if (NUMERIC_IS_SPECIAL(num))
                                862                 :                :     {
                                863         [ -  + ]:             15 :         if (NUMERIC_IS_NAN(num))
 1872 tgl@sss.pgh.pa.us         864                 :UBC           0 :             return false;
 1872 tgl@sss.pgh.pa.us         865                 :CBC          15 :         return true;
                                866                 :                :     }
                                867                 :                : 
                                868                 :                :     /* Integral if there are no digits to the right of the decimal point */
                                869                 :             18 :     init_var_from_num(num, &arg);
                                870                 :                : 
                                871   [ +  +  +  + ]:             18 :     return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
                                872                 :                : }
                                873                 :                : 
                                874                 :                : /*
                                875                 :                :  * make_numeric_typmod() -
                                876                 :                :  *
                                877                 :                :  *  Pack numeric precision and scale values into a typmod.  The upper 16 bits
                                878                 :                :  *  are used for the precision (though actually not all these bits are needed,
                                879                 :                :  *  since the maximum allowed precision is 1000).  The lower 16 bits are for
                                880                 :                :  *  the scale, but since the scale is constrained to the range [-1000, 1000],
                                881                 :                :  *  we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
                                882                 :                :  *  unset, for possible future use.
                                883                 :                :  *
                                884                 :                :  *  For purely historical reasons VARHDRSZ is then added to the result, thus
                                885                 :                :  *  the unused space in the upper 16 bits is not all as freely available as it
                                886                 :                :  *  might seem.  (We can't let the result overflow to a negative int32, as
                                887                 :                :  *  other parts of the system would interpret that as not-a-valid-typmod.)
                                888                 :                :  */
                                889                 :                : static inline int32
 1503 dean.a.rasheed@gmail      890                 :            939 : make_numeric_typmod(int precision, int scale)
                                891                 :                : {
                                892                 :            939 :     return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
                                893                 :                : }
                                894                 :                : 
                                895                 :                : /*
                                896                 :                :  * Because of the offset, valid numeric typmods are at least VARHDRSZ
                                897                 :                :  */
                                898                 :                : static inline bool
                                899                 :          93443 : is_valid_numeric_typmod(int32 typmod)
                                900                 :                : {
                                901                 :          93443 :     return typmod >= (int32) VARHDRSZ;
                                902                 :                : }
                                903                 :                : 
                                904                 :                : /*
                                905                 :                :  * numeric_typmod_precision() -
                                906                 :                :  *
                                907                 :                :  *  Extract the precision from a numeric typmod --- see make_numeric_typmod().
                                908                 :                :  */
                                909                 :                : static inline int
                                910                 :          24268 : numeric_typmod_precision(int32 typmod)
                                911                 :                : {
                                912                 :          24268 :     return ((typmod - VARHDRSZ) >> 16) & 0xffff;
                                913                 :                : }
                                914                 :                : 
                                915                 :                : /*
                                916                 :                :  * numeric_typmod_scale() -
                                917                 :                :  *
                                918                 :                :  *  Extract the scale from a numeric typmod --- see make_numeric_typmod().
                                919                 :                :  *
                                920                 :                :  *  Note that the scale may be negative, so we must do sign extension when
                                921                 :                :  *  unpacking it.  We do this using the bit hack (x^1024)-1024, which sign
                                922                 :                :  *  extends an 11-bit two's complement number x.
                                923                 :                :  */
                                924                 :                : static inline int
                                925                 :          20744 : numeric_typmod_scale(int32 typmod)
                                926                 :                : {
                                927                 :          20744 :     return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
                                928                 :                : }
                                929                 :                : 
                                930                 :                : /*
                                931                 :                :  * numeric_maximum_size() -
                                932                 :                :  *
                                933                 :                :  *  Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
                                934                 :                :  */
                                935                 :                : int32
 5512 rhaas@postgresql.org      936                 :           3524 : numeric_maximum_size(int32 typmod)
                                937                 :                : {
                                938                 :                :     int         precision;
                                939                 :                :     int         numeric_digits;
                                940                 :                : 
 1503 dean.a.rasheed@gmail      941         [ -  + ]:           3524 :     if (!is_valid_numeric_typmod(typmod))
 5517 rhaas@postgresql.org      942                 :UBC           0 :         return -1;
                                943                 :                : 
                                944                 :                :     /* precision (ie, max # of digits) is in upper bits of typmod */
 1503 dean.a.rasheed@gmail      945                 :CBC        3524 :     precision = numeric_typmod_precision(typmod);
                                946                 :                : 
                                947                 :                :     /*
                                948                 :                :      * This formula computes the maximum number of NumericDigits we could need
                                949                 :                :      * in order to store the specified number of decimal digits. Because the
                                950                 :                :      * weight is stored as a number of NumericDigits rather than a number of
                                951                 :                :      * decimal digits, it's possible that the first NumericDigit will contain
                                952                 :                :      * only a single decimal digit.  Thus, the first two decimal digits can
                                953                 :                :      * require two NumericDigits to store, but it isn't until we reach
                                954                 :                :      * DEC_DIGITS + 2 decimal digits that we potentially need a third
                                955                 :                :      * NumericDigit.
                                956                 :                :      */
 5512 rhaas@postgresql.org      957                 :           3524 :     numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
                                958                 :                : 
                                959                 :                :     /*
                                960                 :                :      * In most cases, the size of a numeric will be smaller than the value
                                961                 :                :      * computed below, because the varlena header will typically get toasted
                                962                 :                :      * down to a single byte before being stored on disk, and it may also be
                                963                 :                :      * possible to use a short numeric header.  But our job here is to compute
                                964                 :                :      * the worst case.
                                965                 :                :      */
                                966                 :           3524 :     return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
                                967                 :                : }
                                968                 :                : 
                                969                 :                : /*
                                970                 :                :  * numeric_out_sci() -
                                971                 :                :  *
                                972                 :                :  *  Output function for numeric data type in scientific notation.
                                973                 :                :  */
                                974                 :                : char *
 5871 tgl@sss.pgh.pa.us         975                 :            123 : numeric_out_sci(Numeric num, int scale)
                                976                 :                : {
                                977                 :                :     NumericVar  x;
                                978                 :                :     char       *str;
                                979                 :                : 
                                980                 :                :     /*
                                981                 :                :      * Handle NaN and infinities
                                982                 :                :      */
 1872                           983         [ +  + ]:            123 :     if (NUMERIC_IS_SPECIAL(num))
                                984                 :                :     {
                                985         [ +  + ]:              9 :         if (NUMERIC_IS_PINF(num))
                                986                 :              3 :             return pstrdup("Infinity");
                                987         [ +  + ]:              6 :         else if (NUMERIC_IS_NINF(num))
                                988                 :              3 :             return pstrdup("-Infinity");
                                989                 :                :         else
                                990                 :              3 :             return pstrdup("NaN");
                                991                 :                :     }
                                992                 :                : 
 4672 heikki.linnakangas@i      993                 :            114 :     init_var_from_num(num, &x);
                                994                 :                : 
 5871 tgl@sss.pgh.pa.us         995                 :            114 :     str = get_str_from_var_sci(&x, scale);
                                996                 :                : 
                                997                 :            114 :     return str;
                                998                 :                : }
                                999                 :                : 
                               1000                 :                : /*
                               1001                 :                :  * numeric_normalize() -
                               1002                 :                :  *
                               1003                 :                :  *  Output function for numeric data type, suppressing insignificant trailing
                               1004                 :                :  *  zeroes and then any trailing decimal point.  The intent of this is to
                               1005                 :                :  *  produce strings that are equal if and only if the input numeric values
                               1006                 :                :  *  compare equal.
                               1007                 :                :  */
                               1008                 :                : char *
 4185 andrew@dunslane.net      1009                 :          19224 : numeric_normalize(Numeric num)
                               1010                 :                : {
                               1011                 :                :     NumericVar  x;
                               1012                 :                :     char       *str;
                               1013                 :                :     int         last;
                               1014                 :                : 
                               1015                 :                :     /*
                               1016                 :                :      * Handle NaN and infinities
                               1017                 :                :      */
 1872 tgl@sss.pgh.pa.us        1018         [ -  + ]:          19224 :     if (NUMERIC_IS_SPECIAL(num))
                               1019                 :                :     {
 1872 tgl@sss.pgh.pa.us        1020         [ #  # ]:UBC           0 :         if (NUMERIC_IS_PINF(num))
                               1021                 :              0 :             return pstrdup("Infinity");
                               1022         [ #  # ]:              0 :         else if (NUMERIC_IS_NINF(num))
                               1023                 :              0 :             return pstrdup("-Infinity");
                               1024                 :                :         else
                               1025                 :              0 :             return pstrdup("NaN");
                               1026                 :                :     }
                               1027                 :                : 
 4185 andrew@dunslane.net      1028                 :CBC       19224 :     init_var_from_num(num, &x);
                               1029                 :                : 
                               1030                 :          19224 :     str = get_str_from_var(&x);
                               1031                 :                : 
                               1032                 :                :     /* If there's no decimal point, there's certainly nothing to remove. */
 3957 tgl@sss.pgh.pa.us        1033         [ +  + ]:          19224 :     if (strchr(str, '.') != NULL)
                               1034                 :                :     {
                               1035                 :                :         /*
                               1036                 :                :          * Back up over trailing fractional zeroes.  Since there is a decimal
                               1037                 :                :          * point, this loop will terminate safely.
                               1038                 :                :          */
                               1039                 :             21 :         last = strlen(str) - 1;
                               1040         [ +  + ]:             42 :         while (str[last] == '0')
                               1041                 :             21 :             last--;
                               1042                 :                : 
                               1043                 :                :         /* We want to get rid of the decimal point too, if it's now last. */
                               1044         [ +  - ]:             21 :         if (str[last] == '.')
                               1045                 :             21 :             last--;
                               1046                 :                : 
                               1047                 :                :         /* Delete whatever we backed up over. */
                               1048                 :             21 :         str[last + 1] = '\0';
                               1049                 :                :     }
                               1050                 :                : 
 4185 andrew@dunslane.net      1051                 :          19224 :     return str;
                               1052                 :                : }
                               1053                 :                : 
                               1054                 :                : /*
                               1055                 :                :  *      numeric_recv            - converts external binary format to numeric
                               1056                 :                :  *
                               1057                 :                :  * External format is a sequence of int16's:
                               1058                 :                :  * ndigits, weight, sign, dscale, NumericDigits.
                               1059                 :                :  */
                               1060                 :                : Datum
 8153 tgl@sss.pgh.pa.us        1061                 :             51 : numeric_recv(PG_FUNCTION_ARGS)
                               1062                 :                : {
                               1063                 :             51 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
                               1064                 :                : 
                               1065                 :                : #ifdef NOT_USED
                               1066                 :                :     Oid         typelem = PG_GETARG_OID(1);
                               1067                 :                : #endif
 7363                          1068                 :             51 :     int32       typmod = PG_GETARG_INT32(2);
                               1069                 :                :     NumericVar  value;
                               1070                 :                :     Numeric     res;
                               1071                 :                :     int         len,
                               1072                 :                :                 i;
                               1073                 :                : 
 8153                          1074                 :             51 :     init_var(&value);
                               1075                 :                : 
                               1076                 :             51 :     len = (uint16) pq_getmsgint(buf, sizeof(uint16));
                               1077                 :                : 
                               1078                 :             51 :     alloc_var(&value, len);
                               1079                 :                : 
                               1080                 :             51 :     value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
                               1081                 :                :     /* we allow any int16 for weight --- OK? */
                               1082                 :                : 
                               1083                 :             51 :     value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
                               1084         [ -  + ]:             51 :     if (!(value.sign == NUMERIC_POS ||
 8153 tgl@sss.pgh.pa.us        1085         [ #  # ]:UBC           0 :           value.sign == NUMERIC_NEG ||
 1872                          1086         [ #  # ]:              0 :           value.sign == NUMERIC_NAN ||
                               1087         [ #  # ]:              0 :           value.sign == NUMERIC_PINF ||
                               1088         [ #  # ]:              0 :           value.sign == NUMERIC_NINF))
 8077                          1089         [ #  # ]:              0 :         ereport(ERROR,
                               1090                 :                :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1091                 :                :                  errmsg("invalid sign in external \"numeric\" value")));
                               1092                 :                : 
 8153 tgl@sss.pgh.pa.us        1093                 :CBC          51 :     value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
 3932                          1094         [ -  + ]:             51 :     if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
 3932 tgl@sss.pgh.pa.us        1095         [ #  # ]:UBC           0 :         ereport(ERROR,
                               1096                 :                :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1097                 :                :                  errmsg("invalid scale in external \"numeric\" value")));
                               1098                 :                : 
 8153 tgl@sss.pgh.pa.us        1099         [ +  + ]:CBC         137 :     for (i = 0; i < len; i++)
                               1100                 :                :     {
 8069 bruce@momjian.us         1101                 :             86 :         NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
                               1102                 :                : 
 8153 tgl@sss.pgh.pa.us        1103   [ +  -  -  + ]:             86 :         if (d < 0 || d >= NBASE)
 8077 tgl@sss.pgh.pa.us        1104         [ #  # ]:UBC           0 :             ereport(ERROR,
                               1105                 :                :                     (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1106                 :                :                      errmsg("invalid digit in external \"numeric\" value")));
 8153 tgl@sss.pgh.pa.us        1107                 :CBC          86 :         value.digits[i] = d;
                               1108                 :                :     }
                               1109                 :                : 
                               1110                 :                :     /*
                               1111                 :                :      * If the given dscale would hide any digits, truncate those digits away.
                               1112                 :                :      * We could alternatively throw an error, but that would take a bunch of
                               1113                 :                :      * extra code (about as much as trunc_var involves), and it might cause
                               1114                 :                :      * client compatibility issues.  Be careful not to apply trunc_var to
                               1115                 :                :      * special values, as it could do the wrong thing; we don't need it
                               1116                 :                :      * anyway, since make_result will ignore all but the sign field.
                               1117                 :                :      *
                               1118                 :                :      * After doing that, be sure to check the typmod restriction.
                               1119                 :                :      */
 1872                          1120         [ -  + ]:             51 :     if (value.sign == NUMERIC_POS ||
 1872 tgl@sss.pgh.pa.us        1121         [ #  # ]:UBC           0 :         value.sign == NUMERIC_NEG)
                               1122                 :                :     {
 1872 tgl@sss.pgh.pa.us        1123                 :CBC          51 :         trunc_var(&value, value.dscale);
                               1124                 :                : 
 1002                          1125                 :             51 :         (void) apply_typmod(&value, typmod, NULL);
                               1126                 :                : 
 1872                          1127                 :             51 :         res = make_result(&value);
                               1128                 :                :     }
                               1129                 :                :     else
                               1130                 :                :     {
                               1131                 :                :         /* apply_typmod_special wants us to make the Numeric first */
 1872 tgl@sss.pgh.pa.us        1132                 :UBC           0 :         res = make_result(&value);
                               1133                 :                : 
 1002                          1134                 :              0 :         (void) apply_typmod_special(res, typmod, NULL);
                               1135                 :                :     }
                               1136                 :                : 
 8153 tgl@sss.pgh.pa.us        1137                 :CBC          51 :     free_var(&value);
                               1138                 :                : 
                               1139                 :             51 :     PG_RETURN_NUMERIC(res);
                               1140                 :                : }
                               1141                 :                : 
                               1142                 :                : /*
                               1143                 :                :  *      numeric_send            - converts numeric to binary format
                               1144                 :                :  */
                               1145                 :                : Datum
                               1146                 :             35 : numeric_send(PG_FUNCTION_ARGS)
                               1147                 :                : {
                               1148                 :             35 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1149                 :                :     NumericVar  x;
                               1150                 :                :     StringInfoData buf;
                               1151                 :                :     int         i;
                               1152                 :                : 
 4672 heikki.linnakangas@i     1153                 :             35 :     init_var_from_num(num, &x);
                               1154                 :                : 
 8153 tgl@sss.pgh.pa.us        1155                 :             35 :     pq_begintypsend(&buf);
                               1156                 :                : 
 2887 andres@anarazel.de       1157                 :             35 :     pq_sendint16(&buf, x.ndigits);
                               1158                 :             35 :     pq_sendint16(&buf, x.weight);
                               1159                 :             35 :     pq_sendint16(&buf, x.sign);
                               1160                 :             35 :     pq_sendint16(&buf, x.dscale);
 8153 tgl@sss.pgh.pa.us        1161         [ +  + ]:             97 :     for (i = 0; i < x.ndigits; i++)
 2887 andres@anarazel.de       1162                 :             62 :         pq_sendint16(&buf, x.digits[i]);
                               1163                 :                : 
 8153 tgl@sss.pgh.pa.us        1164                 :             35 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
                               1165                 :                : }
                               1166                 :                : 
                               1167                 :                : 
                               1168                 :                : /*
                               1169                 :                :  * numeric_support()
                               1170                 :                :  *
                               1171                 :                :  * Planner support function for the numeric() length coercion function.
                               1172                 :                :  *
                               1173                 :                :  * Flatten calls that solely represent increases in allowable precision.
                               1174                 :                :  * Scale changes mutate every datum, so they are unoptimizable.  Some values,
                               1175                 :                :  * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
                               1176                 :                :  * an unconstrained numeric to any constrained numeric is also unoptimizable.
                               1177                 :                :  */
                               1178                 :                : Datum
 2401                          1179                 :            258 : numeric_support(PG_FUNCTION_ARGS)
                               1180                 :                : {
                               1181                 :            258 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
 4960 rhaas@postgresql.org     1182                 :            258 :     Node       *ret = NULL;
                               1183                 :                : 
 2401 tgl@sss.pgh.pa.us        1184         [ +  + ]:            258 :     if (IsA(rawreq, SupportRequestSimplify))
                               1185                 :                :     {
                               1186                 :            114 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
                               1187                 :            114 :         FuncExpr   *expr = req->fcall;
                               1188                 :                :         Node       *typmod;
                               1189                 :                : 
                               1190         [ -  + ]:            114 :         Assert(list_length(expr->args) >= 2);
                               1191                 :                : 
                               1192                 :            114 :         typmod = (Node *) lsecond(expr->args);
                               1193                 :                : 
 1939                          1194   [ +  -  +  - ]:            114 :         if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
                               1195                 :                :         {
 2401                          1196                 :            114 :             Node       *source = (Node *) linitial(expr->args);
                               1197                 :            114 :             int32       old_typmod = exprTypmod(source);
                               1198                 :            114 :             int32       new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
 1503 dean.a.rasheed@gmail     1199                 :            114 :             int32       old_scale = numeric_typmod_scale(old_typmod);
                               1200                 :            114 :             int32       new_scale = numeric_typmod_scale(new_typmod);
                               1201                 :            114 :             int32       old_precision = numeric_typmod_precision(old_typmod);
                               1202                 :            114 :             int32       new_precision = numeric_typmod_precision(new_typmod);
                               1203                 :                : 
                               1204                 :                :             /*
                               1205                 :                :              * If new_typmod is invalid, the destination is unconstrained;
                               1206                 :                :              * that's always OK.  If old_typmod is valid, the source is
                               1207                 :                :              * constrained, and we're OK if the scale is unchanged and the
                               1208                 :                :              * precision is not decreasing.  See further notes in function
                               1209                 :                :              * header comment.
                               1210                 :                :              */
                               1211   [ +  -  +  + ]:            228 :             if (!is_valid_numeric_typmod(new_typmod) ||
                               1212         [ +  + ]:            120 :                 (is_valid_numeric_typmod(old_typmod) &&
 2401 tgl@sss.pgh.pa.us        1213         [ +  - ]:              3 :                  new_scale == old_scale && new_precision >= old_precision))
                               1214                 :              3 :                 ret = relabel_to_typmod(source, new_typmod);
                               1215                 :                :         }
                               1216                 :                :     }
                               1217                 :                : 
 4960 rhaas@postgresql.org     1218                 :            258 :     PG_RETURN_POINTER(ret);
                               1219                 :                : }
                               1220                 :                : 
                               1221                 :                : /*
                               1222                 :                :  * numeric() -
                               1223                 :                :  *
                               1224                 :                :  *  This is a special function called by the Postgres database system
                               1225                 :                :  *  before a value is stored in a tuple's attribute. The precision and
                               1226                 :                :  *  scale of the attribute have to be applied on the value.
                               1227                 :                :  */
                               1228                 :                : Datum
 6505 bruce@momjian.us         1229                 :           5851 : numeric     (PG_FUNCTION_ARGS)
                               1230                 :                : {
 9216 tgl@sss.pgh.pa.us        1231                 :           5851 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1232                 :           5851 :     int32       typmod = PG_GETARG_INT32(1);
                               1233                 :                :     Numeric     new;
                               1234                 :                :     int         precision;
                               1235                 :                :     int         scale;
                               1236                 :                :     int         ddigits;
                               1237                 :                :     int         maxdigits;
                               1238                 :                :     int         dscale;
                               1239                 :                :     NumericVar  var;
                               1240                 :                : 
                               1241                 :                :     /*
                               1242                 :                :      * Handle NaN and infinities: if apply_typmod_special doesn't complain,
                               1243                 :                :      * just return a copy of the input.
                               1244                 :                :      */
 1872                          1245         [ +  + ]:           5851 :     if (NUMERIC_IS_SPECIAL(num))
                               1246                 :                :     {
 1002                          1247                 :            105 :         (void) apply_typmod_special(num, typmod, NULL);
 1872                          1248                 :             96 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1249                 :                :     }
                               1250                 :                : 
                               1251                 :                :     /*
                               1252                 :                :      * If the value isn't a valid type modifier, simply return a copy of the
                               1253                 :                :      * input value
                               1254                 :                :      */
 1503 dean.a.rasheed@gmail     1255         [ -  + ]:           5746 :     if (!is_valid_numeric_typmod(typmod))
 1872 tgl@sss.pgh.pa.us        1256                 :UBC           0 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1257                 :                : 
                               1258                 :                :     /*
                               1259                 :                :      * Get the precision and scale out of the typmod value
                               1260                 :                :      */
 1503 dean.a.rasheed@gmail     1261                 :CBC        5746 :     precision = numeric_typmod_precision(typmod);
                               1262                 :           5746 :     scale = numeric_typmod_scale(typmod);
 8205 tgl@sss.pgh.pa.us        1263                 :           5746 :     maxdigits = precision - scale;
                               1264                 :                : 
                               1265                 :                :     /* The target display scale is non-negative */
 1503 dean.a.rasheed@gmail     1266                 :           5746 :     dscale = Max(scale, 0);
                               1267                 :                : 
                               1268                 :                :     /*
                               1269                 :                :      * If the number is certainly in bounds and due to the target scale no
                               1270                 :                :      * rounding could be necessary, just make a copy of the input and modify
                               1271                 :                :      * its scale fields, unless the larger scale forces us to abandon the
                               1272                 :                :      * short representation.  (Note we assume the existing dscale is
                               1273                 :                :      * honest...)
                               1274                 :                :      */
 5513 rhaas@postgresql.org     1275   [ +  +  +  + ]:           5746 :     ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
                               1276   [ +  +  +  +  :           5746 :     if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
                                              +  + ]
 1503 dean.a.rasheed@gmail     1277   [ +  -  +  -  :           3565 :         && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
                                     +  +  +  -  -  
                                     -  +  -  +  +  
                                        -  +  -  - ]
 5263 bruce@momjian.us         1278         [ #  # ]:UBC           0 :             || !NUMERIC_IS_SHORT(num)))
                               1279                 :                :     {
 1872 tgl@sss.pgh.pa.us        1280                 :CBC        3565 :         new = duplicate_numeric(num);
 5513 rhaas@postgresql.org     1281         [ +  - ]:           3565 :         if (NUMERIC_IS_SHORT(num))
                               1282                 :           3565 :             new->choice.n_short.n_header =
                               1283                 :           3565 :                 (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
 1503 dean.a.rasheed@gmail     1284                 :           3565 :                 | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
                               1285                 :                :         else
 5513 rhaas@postgresql.org     1286   [ #  #  #  # ]:UBC           0 :             new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
 1503 dean.a.rasheed@gmail     1287                 :              0 :                 ((uint16) dscale & NUMERIC_DSCALE_MASK);
 9216 tgl@sss.pgh.pa.us        1288                 :CBC        3565 :         PG_RETURN_NUMERIC(new);
                               1289                 :                :     }
                               1290                 :                : 
                               1291                 :                :     /*
                               1292                 :                :      * We really need to fiddle with things - unpack the number into a
                               1293                 :                :      * variable and let apply_typmod() do it.
                               1294                 :                :      */
 9747 JanWieck@Yahoo.com       1295                 :           2181 :     init_var(&var);
                               1296                 :                : 
                               1297                 :           2181 :     set_var_from_num(num, &var);
 1002 tgl@sss.pgh.pa.us        1298                 :           2181 :     (void) apply_typmod(&var, typmod, NULL);
 9747 JanWieck@Yahoo.com       1299                 :           2151 :     new = make_result(&var);
                               1300                 :                : 
                               1301                 :           2151 :     free_var(&var);
                               1302                 :                : 
 9216 tgl@sss.pgh.pa.us        1303                 :           2151 :     PG_RETURN_NUMERIC(new);
                               1304                 :                : }
                               1305                 :                : 
                               1306                 :                : Datum
 6825                          1307                 :            960 : numerictypmodin(PG_FUNCTION_ARGS)
                               1308                 :                : {
 6505 bruce@momjian.us         1309                 :            960 :     ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
                               1310                 :                :     int32      *tl;
                               1311                 :                :     int         n;
                               1312                 :                :     int32       typmod;
                               1313                 :                : 
 6658 tgl@sss.pgh.pa.us        1314                 :            960 :     tl = ArrayGetIntegerTypmods(ta, &n);
                               1315                 :                : 
 6825                          1316         [ +  + ]:            960 :     if (n == 2)
                               1317                 :                :     {
                               1318   [ +  +  +  + ]:            952 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
                               1319         [ +  - ]:              9 :             ereport(ERROR,
                               1320                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1321                 :                :                      errmsg("NUMERIC precision %d must be between 1 and %d",
                               1322                 :                :                             tl[0], NUMERIC_MAX_PRECISION)));
 1503 dean.a.rasheed@gmail     1323   [ +  +  +  + ]:            943 :         if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
 6825 tgl@sss.pgh.pa.us        1324         [ +  - ]:              6 :             ereport(ERROR,
                               1325                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1326                 :                :                      errmsg("NUMERIC scale %d must be between %d and %d",
                               1327                 :                :                             tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
 1503 dean.a.rasheed@gmail     1328                 :            937 :         typmod = make_numeric_typmod(tl[0], tl[1]);
                               1329                 :                :     }
 6825 tgl@sss.pgh.pa.us        1330         [ +  + ]:              8 :     else if (n == 1)
                               1331                 :                :     {
                               1332   [ +  -  -  + ]:              2 :         if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
 6825 tgl@sss.pgh.pa.us        1333         [ #  # ]:UBC           0 :             ereport(ERROR,
                               1334                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1335                 :                :                      errmsg("NUMERIC precision %d must be between 1 and %d",
                               1336                 :                :                             tl[0], NUMERIC_MAX_PRECISION)));
                               1337                 :                :         /* scale defaults to zero */
 1503 dean.a.rasheed@gmail     1338                 :CBC           2 :         typmod = make_numeric_typmod(tl[0], 0);
                               1339                 :                :     }
                               1340                 :                :     else
                               1341                 :                :     {
 6825 tgl@sss.pgh.pa.us        1342         [ +  - ]:              6 :         ereport(ERROR,
                               1343                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1344                 :                :                  errmsg("invalid NUMERIC type modifier")));
                               1345                 :                :         typmod = 0;             /* keep compiler quiet */
                               1346                 :                :     }
                               1347                 :                : 
                               1348                 :            939 :     PG_RETURN_INT32(typmod);
                               1349                 :                : }
                               1350                 :                : 
                               1351                 :                : Datum
                               1352                 :            188 : numerictypmodout(PG_FUNCTION_ARGS)
                               1353                 :                : {
 6505 bruce@momjian.us         1354                 :            188 :     int32       typmod = PG_GETARG_INT32(0);
                               1355                 :            188 :     char       *res = (char *) palloc(64);
                               1356                 :                : 
 1503 dean.a.rasheed@gmail     1357         [ +  - ]:            188 :     if (is_valid_numeric_typmod(typmod))
 6825 tgl@sss.pgh.pa.us        1358                 :            188 :         snprintf(res, 64, "(%d,%d)",
                               1359                 :                :                  numeric_typmod_precision(typmod),
                               1360                 :                :                  numeric_typmod_scale(typmod));
                               1361                 :                :     else
 6825 tgl@sss.pgh.pa.us        1362                 :UBC           0 :         *res = '\0';
                               1363                 :                : 
 6825 tgl@sss.pgh.pa.us        1364                 :CBC         188 :     PG_RETURN_CSTRING(res);
                               1365                 :                : }
                               1366                 :                : 
                               1367                 :                : 
                               1368                 :                : /* ----------------------------------------------------------------------
                               1369                 :                :  *
                               1370                 :                :  * Sign manipulation, rounding and the like
                               1371                 :                :  *
                               1372                 :                :  * ----------------------------------------------------------------------
                               1373                 :                :  */
                               1374                 :                : 
                               1375                 :                : Datum
 9170                          1376                 :           9753 : numeric_abs(PG_FUNCTION_ARGS)
                               1377                 :                : {
                               1378                 :           9753 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1379                 :                :     Numeric     res;
                               1380                 :                : 
                               1381                 :                :     /*
                               1382                 :                :      * Do it the easy way directly on the packed format
                               1383                 :                :      */
 1872                          1384                 :           9753 :     res = duplicate_numeric(num);
                               1385                 :                : 
 5513 rhaas@postgresql.org     1386         [ +  + ]:           9753 :     if (NUMERIC_IS_SHORT(num))
                               1387                 :           9720 :         res->choice.n_short.n_header =
                               1388                 :           9720 :             num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
 1872 tgl@sss.pgh.pa.us        1389         [ +  + ]:             33 :     else if (NUMERIC_IS_SPECIAL(num))
                               1390                 :                :     {
                               1391                 :                :         /* This changes -Inf to Inf, and doesn't affect NaN */
                               1392                 :              9 :         res->choice.n_short.n_header =
                               1393                 :              9 :             num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
                               1394                 :                :     }
                               1395                 :                :     else
 5513 rhaas@postgresql.org     1396         [ -  + ]:             24 :         res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
                               1397                 :                : 
 9170 tgl@sss.pgh.pa.us        1398                 :           9753 :     PG_RETURN_NUMERIC(res);
                               1399                 :                : }
                               1400                 :                : 
                               1401                 :                : 
                               1402                 :                : Datum
                               1403                 :            442 : numeric_uminus(PG_FUNCTION_ARGS)
                               1404                 :                : {
                               1405                 :            442 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1406                 :                :     Numeric     res;
                               1407                 :                : 
                               1408                 :                :     /*
                               1409                 :                :      * Do it the easy way directly on the packed format
                               1410                 :                :      */
 1872                          1411                 :            442 :     res = duplicate_numeric(num);
                               1412                 :                : 
                               1413         [ +  + ]:            442 :     if (NUMERIC_IS_SPECIAL(num))
                               1414                 :                :     {
                               1415                 :                :         /* Flip the sign, if it's Inf or -Inf */
                               1416         [ +  + ]:             63 :         if (!NUMERIC_IS_NAN(num))
                               1417                 :             42 :             res->choice.n_short.n_header =
                               1418                 :             42 :                 num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
                               1419                 :                :     }
                               1420                 :                : 
                               1421                 :                :     /*
                               1422                 :                :      * The packed format is known to be totally zero digit trimmed always. So
                               1423                 :                :      * once we've eliminated specials, we can identify a zero by the fact that
                               1424                 :                :      * there are no digits at all. Do nothing to a zero.
                               1425                 :                :      */
                               1426   [ +  -  +  + ]:            379 :     else if (NUMERIC_NDIGITS(num) != 0)
                               1427                 :                :     {
                               1428                 :                :         /* Else, flip the sign */
 5513 rhaas@postgresql.org     1429         [ +  - ]:            322 :         if (NUMERIC_IS_SHORT(num))
                               1430                 :            322 :             res->choice.n_short.n_header =
                               1431                 :            322 :                 num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
 5513 rhaas@postgresql.org     1432   [ #  #  #  #  :UBC           0 :         else if (NUMERIC_SIGN(num) == NUMERIC_POS)
                                              #  # ]
                               1433                 :              0 :             res->choice.n_long.n_sign_dscale =
                               1434         [ #  # ]:              0 :                 NUMERIC_NEG | NUMERIC_DSCALE(num);
                               1435                 :                :         else
                               1436                 :              0 :             res->choice.n_long.n_sign_dscale =
                               1437         [ #  # ]:              0 :                 NUMERIC_POS | NUMERIC_DSCALE(num);
                               1438                 :                :     }
                               1439                 :                : 
 9170 tgl@sss.pgh.pa.us        1440                 :CBC         442 :     PG_RETURN_NUMERIC(res);
                               1441                 :                : }
                               1442                 :                : 
                               1443                 :                : 
                               1444                 :                : Datum
 8857 bruce@momjian.us         1445                 :            249 : numeric_uplus(PG_FUNCTION_ARGS)
                               1446                 :                : {
                               1447                 :            249 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1448                 :                : 
 1872 tgl@sss.pgh.pa.us        1449                 :            249 :     PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1450                 :                : }
                               1451                 :                : 
                               1452                 :                : 
                               1453                 :                : /*
                               1454                 :                :  * numeric_sign_internal() -
                               1455                 :                :  *
                               1456                 :                :  * Returns -1 if the argument is less than 0, 0 if the argument is equal
                               1457                 :                :  * to 0, and 1 if the argument is greater than zero.  Caller must have
                               1458                 :                :  * taken care of the NaN case, but we can handle infinities here.
                               1459                 :                :  */
                               1460                 :                : static int
                               1461                 :           1785 : numeric_sign_internal(Numeric num)
                               1462                 :                : {
                               1463         [ +  + ]:           1785 :     if (NUMERIC_IS_SPECIAL(num))
                               1464                 :                :     {
                               1465         [ -  + ]:            156 :         Assert(!NUMERIC_IS_NAN(num));
                               1466                 :                :         /* Must be Inf or -Inf */
                               1467         [ +  + ]:            156 :         if (NUMERIC_IS_PINF(num))
                               1468                 :             93 :             return 1;
                               1469                 :                :         else
                               1470                 :             63 :             return -1;
                               1471                 :                :     }
                               1472                 :                : 
                               1473                 :                :     /*
                               1474                 :                :      * The packed format is known to be totally zero digit trimmed always. So
                               1475                 :                :      * once we've eliminated specials, we can identify a zero by the fact that
                               1476                 :                :      * there are no digits at all.
                               1477                 :                :      */
                               1478   [ +  +  +  + ]:           1629 :     else if (NUMERIC_NDIGITS(num) == 0)
                               1479                 :            114 :         return 0;
                               1480   [ +  +  -  +  :           1515 :     else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
                                              +  + ]
                               1481                 :            366 :         return -1;
                               1482                 :                :     else
                               1483                 :           1149 :         return 1;
                               1484                 :                : }
                               1485                 :                : 
                               1486                 :                : /*
                               1487                 :                :  * numeric_sign() -
                               1488                 :                :  *
                               1489                 :                :  * returns -1 if the argument is less than 0, 0 if the argument is equal
                               1490                 :                :  * to 0, and 1 if the argument is greater than zero.
                               1491                 :                :  */
                               1492                 :                : Datum
 9170                          1493                 :             24 : numeric_sign(PG_FUNCTION_ARGS)
                               1494                 :                : {
                               1495                 :             24 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1496                 :                : 
                               1497                 :                :     /*
                               1498                 :                :      * Handle NaN (infinities can be handled normally)
                               1499                 :                :      */
 9747 JanWieck@Yahoo.com       1500         [ +  + ]:             24 :     if (NUMERIC_IS_NAN(num))
 9170 tgl@sss.pgh.pa.us        1501                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               1502                 :                : 
 1872                          1503   [ +  +  +  - ]:             21 :     switch (numeric_sign_internal(num))
                               1504                 :                :     {
                               1505                 :              3 :         case 0:
                               1506                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               1507                 :              9 :         case 1:
                               1508                 :              9 :             PG_RETURN_NUMERIC(make_result(&const_one));
                               1509                 :              9 :         case -1:
                               1510                 :              9 :             PG_RETURN_NUMERIC(make_result(&const_minus_one));
                               1511                 :                :     }
                               1512                 :                : 
 1872 tgl@sss.pgh.pa.us        1513                 :UBC           0 :     Assert(false);
                               1514                 :                :     return (Datum) 0;
                               1515                 :                : }
                               1516                 :                : 
                               1517                 :                : 
                               1518                 :                : /*
                               1519                 :                :  * numeric_round() -
                               1520                 :                :  *
                               1521                 :                :  *  Round a value to have 'scale' digits after the decimal point.
                               1522                 :                :  *  We allow negative 'scale', implying rounding before the decimal
                               1523                 :                :  *  point --- Oracle interprets rounding that way.
                               1524                 :                :  */
                               1525                 :                : Datum
 9216 tgl@sss.pgh.pa.us        1526                 :CBC        3904 : numeric_round(PG_FUNCTION_ARGS)
                               1527                 :                : {
                               1528                 :           3904 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1529                 :           3904 :     int32       scale = PG_GETARG_INT32(1);
                               1530                 :                :     Numeric     res;
                               1531                 :                :     NumericVar  arg;
                               1532                 :                : 
                               1533                 :                :     /*
                               1534                 :                :      * Handle NaN and infinities
                               1535                 :                :      */
 1872                          1536         [ +  + ]:           3904 :     if (NUMERIC_IS_SPECIAL(num))
                               1537                 :             48 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1538                 :                : 
                               1539                 :                :     /*
                               1540                 :                :      * Limit the scale value to avoid possible overflow in calculations.
                               1541                 :                :      *
                               1542                 :                :      * These limits are based on the maximum number of digits a Numeric value
                               1543                 :                :      * can have before and after the decimal point, but we must allow for one
                               1544                 :                :      * extra digit before the decimal point, in case the most significant
                               1545                 :                :      * digit rounds up; we must check if that causes Numeric overflow.
                               1546                 :                :      */
  425 dean.a.rasheed@gmail     1547                 :           3856 :     scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
                               1548                 :           3856 :     scale = Min(scale, NUMERIC_DSCALE_MAX);
                               1549                 :                : 
                               1550                 :                :     /*
                               1551                 :                :      * Unpack the argument and round it at the proper digit position
                               1552                 :                :      */
 9308 tgl@sss.pgh.pa.us        1553                 :           3856 :     init_var(&arg);
                               1554                 :           3856 :     set_var_from_num(num, &arg);
                               1555                 :                : 
 8205                          1556                 :           3856 :     round_var(&arg, scale);
                               1557                 :                : 
                               1558                 :                :     /* We don't allow negative output dscale */
                               1559         [ +  + ]:           3856 :     if (scale < 0)
                               1560                 :            108 :         arg.dscale = 0;
                               1561                 :                : 
                               1562                 :                :     /*
                               1563                 :                :      * Return the rounded result
                               1564                 :                :      */
 9308                          1565                 :           3856 :     res = make_result(&arg);
                               1566                 :                : 
                               1567                 :           3853 :     free_var(&arg);
 9216                          1568                 :           3853 :     PG_RETURN_NUMERIC(res);
                               1569                 :                : }
                               1570                 :                : 
                               1571                 :                : 
                               1572                 :                : /*
                               1573                 :                :  * numeric_trunc() -
                               1574                 :                :  *
                               1575                 :                :  *  Truncate a value to have 'scale' digits after the decimal point.
                               1576                 :                :  *  We allow negative 'scale', implying a truncation before the decimal
                               1577                 :                :  *  point --- Oracle interprets truncation that way.
                               1578                 :                :  */
                               1579                 :                : Datum
                               1580                 :            313 : numeric_trunc(PG_FUNCTION_ARGS)
                               1581                 :                : {
                               1582                 :            313 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               1583                 :            313 :     int32       scale = PG_GETARG_INT32(1);
                               1584                 :                :     Numeric     res;
                               1585                 :                :     NumericVar  arg;
                               1586                 :                : 
                               1587                 :                :     /*
                               1588                 :                :      * Handle NaN and infinities
                               1589                 :                :      */
 1872                          1590         [ +  + ]:            313 :     if (NUMERIC_IS_SPECIAL(num))
                               1591                 :             18 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1592                 :                : 
                               1593                 :                :     /*
                               1594                 :                :      * Limit the scale value to avoid possible overflow in calculations.
                               1595                 :                :      *
                               1596                 :                :      * These limits are based on the maximum number of digits a Numeric value
                               1597                 :                :      * can have before and after the decimal point.
                               1598                 :                :      */
  425 dean.a.rasheed@gmail     1599                 :            295 :     scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS);
                               1600                 :            295 :     scale = Min(scale, NUMERIC_DSCALE_MAX);
                               1601                 :                : 
                               1602                 :                :     /*
                               1603                 :                :      * Unpack the argument and truncate it at the proper digit position
                               1604                 :                :      */
 9747 JanWieck@Yahoo.com       1605                 :            295 :     init_var(&arg);
                               1606                 :            295 :     set_var_from_num(num, &arg);
                               1607                 :                : 
 8205 tgl@sss.pgh.pa.us        1608                 :            295 :     trunc_var(&arg, scale);
                               1609                 :                : 
                               1610                 :                :     /* We don't allow negative output dscale */
                               1611         [ +  + ]:            295 :     if (scale < 0)
                               1612                 :             12 :         arg.dscale = 0;
                               1613                 :                : 
                               1614                 :                :     /*
                               1615                 :                :      * Return the truncated result
                               1616                 :                :      */
 9747 JanWieck@Yahoo.com       1617                 :            295 :     res = make_result(&arg);
                               1618                 :                : 
                               1619                 :            295 :     free_var(&arg);
 9216 tgl@sss.pgh.pa.us        1620                 :            295 :     PG_RETURN_NUMERIC(res);
                               1621                 :                : }
                               1622                 :                : 
                               1623                 :                : 
                               1624                 :                : /*
                               1625                 :                :  * numeric_ceil() -
                               1626                 :                :  *
                               1627                 :                :  *  Return the smallest integer greater than or equal to the argument
                               1628                 :                :  */
                               1629                 :                : Datum
 9170                          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                 :                :      */
 1872                          1639         [ +  + ]:            111 :     if (NUMERIC_IS_SPECIAL(num))
                               1640                 :              9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1641                 :                : 
 4672 heikki.linnakangas@i     1642                 :            102 :     init_var_from_num(num, &result);
 9747 JanWieck@Yahoo.com       1643                 :            102 :     ceil_var(&result, &result);
                               1644                 :                : 
                               1645                 :            102 :     res = make_result(&result);
                               1646                 :            102 :     free_var(&result);
                               1647                 :                : 
 9170 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                 :                :      */
 1872                          1667         [ +  + ]:             63 :     if (NUMERIC_IS_SPECIAL(num))
                               1668                 :              9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               1669                 :                : 
 4672 heikki.linnakangas@i     1670                 :             54 :     init_var_from_num(num, &result);
 9747 JanWieck@Yahoo.com       1671                 :             54 :     floor_var(&result, &result);
                               1672                 :                : 
                               1673                 :             54 :     res = make_result(&result);
                               1674                 :             54 :     free_var(&result);
                               1675                 :                : 
 9170 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
 3952 fujii@postgresql.org     1686                 :          60192 : generate_series_numeric(PG_FUNCTION_ARGS)
                               1687                 :                : {
                               1688                 :          60192 :     return generate_series_step_numeric(fcinfo);
                               1689                 :                : }
                               1690                 :                : 
                               1691                 :                : Datum
                               1692                 :          60417 : generate_series_step_numeric(PG_FUNCTION_ARGS)
                               1693                 :                : {
                               1694                 :                :     generate_series_numeric_fctx *fctx;
                               1695                 :                :     FuncCallContext *funcctx;
                               1696                 :                :     MemoryContext oldcontext;
                               1697                 :                : 
                               1698         [ +  + ]:          60417 :     if (SRF_IS_FIRSTCALL())
                               1699                 :                :     {
                               1700                 :             87 :         Numeric     start_num = PG_GETARG_NUMERIC(0);
                               1701                 :             87 :         Numeric     stop_num = PG_GETARG_NUMERIC(1);
                               1702                 :             87 :         NumericVar  steploc = const_one;
                               1703                 :                : 
                               1704                 :                :         /* Reject NaN and infinities in start and stop values */
 1872 tgl@sss.pgh.pa.us        1705         [ +  + ]:             87 :         if (NUMERIC_IS_SPECIAL(start_num))
                               1706                 :                :         {
                               1707         [ +  + ]:              6 :             if (NUMERIC_IS_NAN(start_num))
                               1708         [ +  - ]:              3 :                 ereport(ERROR,
                               1709                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1710                 :                :                          errmsg("start value cannot be NaN")));
                               1711                 :                :             else
                               1712         [ +  - ]:              3 :                 ereport(ERROR,
                               1713                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1714                 :                :                          errmsg("start value cannot be infinity")));
                               1715                 :                :         }
                               1716         [ +  + ]:             81 :         if (NUMERIC_IS_SPECIAL(stop_num))
                               1717                 :                :         {
                               1718         [ +  + ]:              6 :             if (NUMERIC_IS_NAN(stop_num))
                               1719         [ +  - ]:              3 :                 ereport(ERROR,
                               1720                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1721                 :                :                          errmsg("stop value cannot be NaN")));
                               1722                 :                :             else
                               1723         [ +  - ]:              3 :                 ereport(ERROR,
                               1724                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1725                 :                :                          errmsg("stop value cannot be infinity")));
                               1726                 :                :         }
                               1727                 :                : 
                               1728                 :                :         /* see if we were given an explicit step size */
 3952 fujii@postgresql.org     1729         [ +  + ]:             75 :         if (PG_NARGS() == 3)
                               1730                 :                :         {
 3850 tgl@sss.pgh.pa.us        1731                 :             36 :             Numeric     step_num = PG_GETARG_NUMERIC(2);
                               1732                 :                : 
 1872                          1733         [ +  + ]:             36 :             if (NUMERIC_IS_SPECIAL(step_num))
                               1734                 :                :             {
                               1735         [ +  + ]:              6 :                 if (NUMERIC_IS_NAN(step_num))
                               1736         [ +  - ]:              3 :                     ereport(ERROR,
                               1737                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1738                 :                :                              errmsg("step size cannot be NaN")));
                               1739                 :                :                 else
                               1740         [ +  - ]:              3 :                     ereport(ERROR,
                               1741                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1742                 :                :                              errmsg("step size cannot be infinity")));
                               1743                 :                :             }
                               1744                 :                : 
 3952 fujii@postgresql.org     1745                 :             30 :             init_var_from_num(step_num, &steploc);
                               1746                 :                : 
                               1747         [ +  + ]:             30 :             if (cmp_var(&steploc, &const_zero) == 0)
                               1748         [ +  - ]:              3 :                 ereport(ERROR,
                               1749                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1750                 :                :                          errmsg("step size cannot equal zero")));
                               1751                 :                :         }
                               1752                 :                : 
                               1753                 :                :         /* create a function context for cross-call persistence */
                               1754                 :             66 :         funcctx = SRF_FIRSTCALL_INIT();
                               1755                 :                : 
                               1756                 :                :         /*
                               1757                 :                :          * Switch to memory context appropriate for multiple function calls.
                               1758                 :                :          */
                               1759                 :             66 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                               1760                 :                : 
                               1761                 :                :         /* allocate memory for user context */
                               1762                 :                :         fctx = (generate_series_numeric_fctx *)
                               1763                 :             66 :             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                 :                :          */
 3915                          1771                 :             66 :         init_var(&fctx->current);
                               1772                 :             66 :         init_var(&fctx->stop);
 3952                          1773                 :             66 :         init_var(&fctx->step);
                               1774                 :                : 
 3915                          1775                 :             66 :         set_var_from_num(start_num, &fctx->current);
                               1776                 :             66 :         set_var_from_num(stop_num, &fctx->stop);
 3952                          1777                 :             66 :         set_var_from_var(&steploc, &fctx->step);
                               1778                 :                : 
                               1779                 :             66 :         funcctx->user_fctx = fctx;
                               1780                 :             66 :         MemoryContextSwitchTo(oldcontext);
                               1781                 :                :     }
                               1782                 :                : 
                               1783                 :                :     /* stuff done on every call of the function */
                               1784                 :          60396 :     funcctx = SRF_PERCALL_SETUP();
                               1785                 :                : 
                               1786                 :                :     /*
                               1787                 :                :      * Get the saved state and use current state as the result of this
                               1788                 :                :      * iteration.
                               1789                 :                :      */
                               1790                 :          60396 :     fctx = funcctx->user_fctx;
                               1791                 :                : 
                               1792   [ +  +  +  + ]:         120702 :     if ((fctx->step.sign == NUMERIC_POS &&
                               1793                 :          60306 :          cmp_var(&fctx->current, &fctx->stop) <= 0) ||
                               1794   [ +  +  +  + ]:            240 :         (fctx->step.sign == NUMERIC_NEG &&
                               1795                 :             90 :          cmp_var(&fctx->current, &fctx->stop) >= 0))
                               1796                 :                :     {
 3850 tgl@sss.pgh.pa.us        1797                 :          60330 :         Numeric     result = make_result(&fctx->current);
                               1798                 :                : 
                               1799                 :                :         /* switch to memory context appropriate for iteration calculation */
 3952 fujii@postgresql.org     1800                 :          60330 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                               1801                 :                : 
                               1802                 :                :         /* increment current in preparation for next iteration */
                               1803                 :          60330 :         add_var(&fctx->current, &fctx->step, &fctx->current);
                               1804                 :          60330 :         MemoryContextSwitchTo(oldcontext);
                               1805                 :                : 
                               1806                 :                :         /* do when there is more left to send */
                               1807                 :          60330 :         SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
                               1808                 :                :     }
                               1809                 :                :     else
                               1810                 :                :         /* do when there is no more left */
                               1811                 :             66 :         SRF_RETURN_DONE(funcctx);
                               1812                 :                : }
                               1813                 :                : 
                               1814                 :                : /*
                               1815                 :                :  * Planner support function for generate_series(numeric, numeric [, numeric])
                               1816                 :                :  */
                               1817                 :                : Datum
  278 dean.a.rasheed@gmail     1818                 :            243 : generate_series_numeric_support(PG_FUNCTION_ARGS)
                               1819                 :                : {
                               1820                 :            243 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
                               1821                 :            243 :     Node       *ret = NULL;
                               1822                 :                : 
                               1823         [ +  + ]:            243 :     if (IsA(rawreq, SupportRequestRows))
                               1824                 :                :     {
                               1825                 :                :         /* Try to estimate the number of rows returned */
                               1826                 :             78 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
                               1827                 :                : 
                               1828         [ +  - ]:             78 :         if (is_funcclause(req->node))    /* be paranoid */
                               1829                 :                :         {
                               1830                 :             78 :             List       *args = ((FuncExpr *) req->node)->args;
                               1831                 :                :             Node       *arg1,
                               1832                 :                :                        *arg2,
                               1833                 :                :                        *arg3;
                               1834                 :                : 
                               1835                 :                :             /* We can use estimated argument values here */
                               1836                 :             78 :             arg1 = estimate_expression_value(req->root, linitial(args));
                               1837                 :             78 :             arg2 = estimate_expression_value(req->root, lsecond(args));
                               1838         [ +  + ]:             78 :             if (list_length(args) >= 3)
                               1839                 :             51 :                 arg3 = estimate_expression_value(req->root, lthird(args));
                               1840                 :                :             else
                               1841                 :             27 :                 arg3 = NULL;
                               1842                 :                : 
                               1843                 :                :             /*
                               1844                 :                :              * If any argument is constant NULL, we can safely assume that
                               1845                 :                :              * zero rows are returned.  Otherwise, if they're all non-NULL
                               1846                 :                :              * constants, we can calculate the number of rows that will be
                               1847                 :                :              * returned.
                               1848                 :                :              */
                               1849         [ +  + ]:             78 :             if ((IsA(arg1, Const) &&
                               1850         [ +  - ]:             75 :                  ((Const *) arg1)->constisnull) ||
                               1851         [ +  + ]:             78 :                 (IsA(arg2, Const) &&
                               1852   [ +  -  +  + ]:             78 :                  ((Const *) arg2)->constisnull) ||
                               1853         [ +  + ]:             51 :                 (arg3 != NULL && IsA(arg3, Const) &&
                               1854         [ -  + ]:             48 :                  ((Const *) arg3)->constisnull))
                               1855                 :                :             {
  278 dean.a.rasheed@gmail     1856                 :UBC           0 :                 req->rows = 0;
                               1857                 :              0 :                 ret = (Node *) req;
                               1858                 :                :             }
  278 dean.a.rasheed@gmail     1859         [ +  + ]:CBC          78 :             else if (IsA(arg1, Const) &&
                               1860   [ +  +  +  + ]:             75 :                      IsA(arg2, Const) &&
                               1861         [ +  + ]:             51 :                      (arg3 == NULL || IsA(arg3, Const)))
                               1862                 :                :             {
                               1863                 :                :                 Numeric     start_num;
                               1864                 :                :                 Numeric     stop_num;
                               1865                 :             69 :                 NumericVar  step = const_one;
                               1866                 :                : 
                               1867                 :                :                 /*
                               1868                 :                :                  * If any argument is NaN or infinity, generate_series() will
                               1869                 :                :                  * error out, so we needn't produce an estimate.
                               1870                 :                :                  */
                               1871                 :             69 :                 start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
                               1872                 :             69 :                 stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
                               1873                 :                : 
                               1874         [ +  + ]:             69 :                 if (NUMERIC_IS_SPECIAL(start_num) ||
                               1875         [ +  + ]:             60 :                     NUMERIC_IS_SPECIAL(stop_num))
                               1876                 :             24 :                     PG_RETURN_POINTER(NULL);
                               1877                 :                : 
                               1878         [ +  + ]:             54 :                 if (arg3)
                               1879                 :                :                 {
                               1880                 :                :                     Numeric     step_num;
                               1881                 :                : 
                               1882                 :             33 :                     step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
                               1883                 :                : 
                               1884         [ +  + ]:             33 :                     if (NUMERIC_IS_SPECIAL(step_num))
                               1885                 :              9 :                         PG_RETURN_POINTER(NULL);
                               1886                 :                : 
                               1887                 :             24 :                     init_var_from_num(step_num, &step);
                               1888                 :                :                 }
                               1889                 :                : 
                               1890                 :                :                 /*
                               1891                 :                :                  * The number of rows that will be returned is given by
                               1892                 :                :                  * floor((stop - start) / step) + 1, if the sign of step
                               1893                 :                :                  * matches the sign of stop - start.  Otherwise, no rows will
                               1894                 :                :                  * be returned.
                               1895                 :                :                  */
                               1896         [ +  + ]:             45 :                 if (cmp_var(&step, &const_zero) != 0)
                               1897                 :                :                 {
                               1898                 :                :                     NumericVar  start;
                               1899                 :                :                     NumericVar  stop;
                               1900                 :                :                     NumericVar  res;
                               1901                 :                : 
                               1902                 :             39 :                     init_var_from_num(start_num, &start);
                               1903                 :             39 :                     init_var_from_num(stop_num, &stop);
                               1904                 :                : 
                               1905                 :             39 :                     init_var(&res);
                               1906                 :             39 :                     sub_var(&stop, &start, &res);
                               1907                 :                : 
                               1908         [ +  + ]:             39 :                     if (step.sign != res.sign)
                               1909                 :                :                     {
                               1910                 :                :                         /* no rows will be returned */
                               1911                 :              3 :                         req->rows = 0;
                               1912                 :              3 :                         ret = (Node *) req;
                               1913                 :                :                     }
                               1914                 :                :                     else
                               1915                 :                :                     {
                               1916         [ +  + ]:             36 :                         if (arg3)
                               1917                 :             15 :                             div_var(&res, &step, &res, 0, false, false);
                               1918                 :                :                         else
                               1919                 :             21 :                             trunc_var(&res, 0); /* step = 1 */
                               1920                 :                : 
                               1921                 :             36 :                         req->rows = numericvar_to_double_no_overflow(&res) + 1;
                               1922                 :             36 :                         ret = (Node *) req;
                               1923                 :                :                     }
                               1924                 :                : 
                               1925                 :             39 :                     free_var(&res);
                               1926                 :                :                 }
                               1927                 :                :             }
                               1928                 :                :         }
                               1929                 :                :     }
                               1930                 :                : 
                               1931                 :            219 :     PG_RETURN_POINTER(ret);
                               1932                 :                : }
                               1933                 :                : 
                               1934                 :                : 
                               1935                 :                : /*
                               1936                 :                :  * Implements the numeric version of the width_bucket() function
                               1937                 :                :  * defined by SQL2003. See also width_bucket_float8().
                               1938                 :                :  *
                               1939                 :                :  * 'bound1' and 'bound2' are the lower and upper bounds of the
                               1940                 :                :  * histogram's range, respectively. 'count' is the number of buckets
                               1941                 :                :  * in the histogram. width_bucket() returns an integer indicating the
                               1942                 :                :  * bucket number that 'operand' belongs to in an equiwidth histogram
                               1943                 :                :  * with the specified characteristics. An operand smaller than the
                               1944                 :                :  * lower bound is assigned to bucket 0. An operand greater than or equal
                               1945                 :                :  * to the upper bound is assigned to an additional bucket (with number
                               1946                 :                :  * count+1). We don't allow the histogram bounds to be NaN or +/- infinity,
                               1947                 :                :  * but we do allow those values for the operand (taking NaN to be larger
                               1948                 :                :  * than any other value, as we do in comparisons).
                               1949                 :                :  */
                               1950                 :                : Datum
 7785 neilc@samurai.com        1951                 :            393 : width_bucket_numeric(PG_FUNCTION_ARGS)
                               1952                 :                : {
                               1953                 :            393 :     Numeric     operand = PG_GETARG_NUMERIC(0);
                               1954                 :            393 :     Numeric     bound1 = PG_GETARG_NUMERIC(1);
                               1955                 :            393 :     Numeric     bound2 = PG_GETARG_NUMERIC(2);
                               1956                 :            393 :     int32       count = PG_GETARG_INT32(3);
                               1957                 :                :     NumericVar  count_var;
                               1958                 :                :     NumericVar  result_var;
                               1959                 :                :     int32       result;
                               1960                 :                : 
                               1961         [ +  + ]:            393 :     if (count <= 0)
                               1962         [ +  - ]:              6 :         ereport(ERROR,
                               1963                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1964                 :                :                  errmsg("count must be greater than zero")));
                               1965                 :                : 
   66 tgl@sss.pgh.pa.us        1966   [ +  +  +  + ]:GNC         387 :     if (NUMERIC_IS_SPECIAL(bound1) || NUMERIC_IS_SPECIAL(bound2))
                               1967                 :                :     {
                               1968   [ +  +  -  + ]:             12 :         if (NUMERIC_IS_NAN(bound1) || NUMERIC_IS_NAN(bound2))
 1872 tgl@sss.pgh.pa.us        1969         [ +  - ]:CBC           3 :             ereport(ERROR,
                               1970                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1971                 :                :                      errmsg("lower and upper bounds cannot be NaN")));
                               1972                 :                : 
 1794                          1973   [ +  +  +  - ]:              9 :         if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
 1872                          1974         [ +  - ]:              9 :             ereport(ERROR,
                               1975                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1976                 :                :                      errmsg("lower and upper bounds must be finite")));
                               1977                 :                :     }
                               1978                 :                : 
 7785 neilc@samurai.com        1979                 :            375 :     init_var(&result_var);
                               1980                 :            375 :     init_var(&count_var);
                               1981                 :                : 
                               1982                 :                :     /* Convert 'count' to a numeric, for ease of use later */
 3823 andres@anarazel.de       1983                 :            375 :     int64_to_numericvar((int64) count, &count_var);
                               1984                 :                : 
 7785 neilc@samurai.com        1985   [ +  +  +  - ]:            375 :     switch (cmp_numerics(bound1, bound2))
                               1986                 :                :     {
                               1987                 :              3 :         case 0:
                               1988         [ +  - ]:              3 :             ereport(ERROR,
                               1989                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
                               1990                 :                :                      errmsg("lower bound cannot equal upper bound")));
                               1991                 :                :             break;
                               1992                 :                : 
                               1993                 :                :             /* bound1 < bound2 */
                               1994                 :            276 :         case -1:
                               1995         [ +  + ]:            276 :             if (cmp_numerics(operand, bound1) < 0)
                               1996                 :             57 :                 set_var_from_var(&const_zero, &result_var);
                               1997         [ +  + ]:            219 :             else if (cmp_numerics(operand, bound2) >= 0)
                               1998                 :             57 :                 add_var(&count_var, &const_one, &result_var);
                               1999                 :                :             else
  423 dean.a.rasheed@gmail     2000                 :            162 :                 compute_bucket(operand, bound1, bound2, &count_var,
                               2001                 :                :                                &result_var);
 7785 neilc@samurai.com        2002                 :            276 :             break;
                               2003                 :                : 
                               2004                 :                :             /* bound1 > bound2 */
                               2005                 :             96 :         case 1:
                               2006         [ +  + ]:             96 :             if (cmp_numerics(operand, bound1) > 0)
                               2007                 :              6 :                 set_var_from_var(&const_zero, &result_var);
                               2008         [ +  + ]:             90 :             else if (cmp_numerics(operand, bound2) <= 0)
                               2009                 :             12 :                 add_var(&count_var, &const_one, &result_var);
                               2010                 :                :             else
  423 dean.a.rasheed@gmail     2011                 :             78 :                 compute_bucket(operand, bound1, bound2, &count_var,
                               2012                 :                :                                &result_var);
 7785 neilc@samurai.com        2013                 :             96 :             break;
                               2014                 :                :     }
                               2015                 :                : 
                               2016                 :                :     /* if result exceeds the range of a legal int4, we ereport here */
 2366 akorotkov@postgresql     2017         [ -  + ]:            372 :     if (!numericvar_to_int32(&result_var, &result))
 2366 akorotkov@postgresql     2018         [ #  # ]:UBC           0 :         ereport(ERROR,
                               2019                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               2020                 :                :                  errmsg("integer out of range")));
                               2021                 :                : 
 7785 neilc@samurai.com        2022                 :CBC         372 :     free_var(&count_var);
                               2023                 :            372 :     free_var(&result_var);
                               2024                 :                : 
                               2025                 :            372 :     PG_RETURN_INT32(result);
                               2026                 :                : }
                               2027                 :                : 
                               2028                 :                : /*
                               2029                 :                :  * 'operand' is inside the bucket range, so determine the correct
                               2030                 :                :  * bucket for it to go in. The calculations performed by this function
                               2031                 :                :  * are derived directly from the SQL2003 spec. Note however that we
                               2032                 :                :  * multiply by count before dividing, to avoid unnecessary roundoff error.
                               2033                 :                :  */
                               2034                 :                : static void
                               2035                 :            240 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
                               2036                 :                :                const NumericVar *count_var, NumericVar *result_var)
                               2037                 :                : {
                               2038                 :                :     NumericVar  bound1_var;
                               2039                 :                :     NumericVar  bound2_var;
                               2040                 :                :     NumericVar  operand_var;
                               2041                 :                : 
 4672 heikki.linnakangas@i     2042                 :            240 :     init_var_from_num(bound1, &bound1_var);
                               2043                 :            240 :     init_var_from_num(bound2, &bound2_var);
                               2044                 :            240 :     init_var_from_num(operand, &operand_var);
                               2045                 :                : 
                               2046                 :                :     /*
                               2047                 :                :      * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
                               2048                 :                :      * bound1 <= operand < bound2 or bound1 >= operand > bound2.  Either way,
                               2049                 :                :      * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
                               2050                 :                :      * where the quotient is computed using floor division (i.e., division to
                               2051                 :                :      * zero decimal places with truncation), which guarantees that the result
                               2052                 :                :      * is in the range [1, count].  Reversing the bounds doesn't affect the
                               2053                 :                :      * computation, because the signs cancel out when dividing.
                               2054                 :                :      */
  423 dean.a.rasheed@gmail     2055                 :            240 :     sub_var(&operand_var, &bound1_var, &operand_var);
                               2056                 :            240 :     sub_var(&bound2_var, &bound1_var, &bound2_var);
                               2057                 :                : 
 1794 tgl@sss.pgh.pa.us        2058                 :            240 :     mul_var(&operand_var, count_var, &operand_var,
                               2059                 :            240 :             operand_var.dscale + count_var->dscale);
  337 dean.a.rasheed@gmail     2060                 :            240 :     div_var(&operand_var, &bound2_var, result_var, 0, false, true);
  423                          2061                 :            240 :     add_var(result_var, &const_one, result_var);
                               2062                 :                : 
 7785 neilc@samurai.com        2063                 :            240 :     free_var(&bound1_var);
                               2064                 :            240 :     free_var(&bound2_var);
                               2065                 :            240 :     free_var(&operand_var);
 7678 bruce@momjian.us         2066                 :            240 : }
                               2067                 :                : 
                               2068                 :                : /* ----------------------------------------------------------------------
                               2069                 :                :  *
                               2070                 :                :  * Comparison functions
                               2071                 :                :  *
                               2072                 :                :  * Note: btree indexes need these routines not to leak memory; therefore,
                               2073                 :                :  * be careful to free working copies of toasted datums.  Most places don't
                               2074                 :                :  * need to be so careful.
                               2075                 :                :  *
                               2076                 :                :  * Sort support:
                               2077                 :                :  *
                               2078                 :                :  * We implement the sortsupport strategy routine in order to get the benefit of
                               2079                 :                :  * abbreviation. The ordinary numeric comparison can be quite slow as a result
                               2080                 :                :  * of palloc/pfree cycles (due to detoasting packed values for alignment);
                               2081                 :                :  * while this could be worked on itself, the abbreviation strategy gives more
                               2082                 :                :  * speedup in many common cases.
                               2083                 :                :  *
                               2084                 :                :  * The abbreviated format is an int64. The representation is negated relative
                               2085                 :                :  * to the original value, because we use the largest negative value for NaN,
                               2086                 :                :  * which sorts higher than other values. We convert the absolute value of the
                               2087                 :                :  * numeric to a 63-bit positive value, and then negate it if the original
                               2088                 :                :  * number was positive.
                               2089                 :                :  *
                               2090                 :                :  * We abort the abbreviation process if the abbreviation cardinality is below
                               2091                 :                :  * 0.01% of the row count (1 per 10k non-null rows).  The actual break-even
                               2092                 :                :  * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
                               2093                 :                :  * very small penalty), but we don't want to build up too many abbreviated
                               2094                 :                :  * values before first testing for abort, so we take the slightly pessimistic
                               2095                 :                :  * number.  We make no attempt to estimate the cardinality of the real values,
                               2096                 :                :  * since it plays no part in the cost model here (if the abbreviation is equal,
                               2097                 :                :  * the cost of comparing equal and unequal underlying values is comparable).
                               2098                 :                :  * We discontinue even checking for abort (saving us the hashing overhead) if
                               2099                 :                :  * the estimated cardinality gets to 100k; that would be enough to support many
                               2100                 :                :  * billions of rows while doing no worse than breaking even.
                               2101                 :                :  *
                               2102                 :                :  * ----------------------------------------------------------------------
                               2103                 :                :  */
                               2104                 :                : 
                               2105                 :                : /*
                               2106                 :                :  * Sort support strategy routine.
                               2107                 :                :  */
                               2108                 :                : Datum
 3810 rhaas@postgresql.org     2109                 :            570 : numeric_sortsupport(PG_FUNCTION_ARGS)
                               2110                 :                : {
                               2111                 :            570 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
                               2112                 :                : 
                               2113                 :            570 :     ssup->comparator = numeric_fast_cmp;
                               2114                 :                : 
                               2115         [ +  + ]:            570 :     if (ssup->abbreviate)
                               2116                 :                :     {
                               2117                 :                :         NumericSortSupport *nss;
                               2118                 :            129 :         MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
                               2119                 :                : 
                               2120                 :            129 :         nss = palloc(sizeof(NumericSortSupport));
                               2121                 :                : 
                               2122                 :                :         /*
                               2123                 :                :          * palloc a buffer for handling unaligned packed values in addition to
                               2124                 :                :          * the support struct
                               2125                 :                :          */
                               2126                 :            129 :         nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
                               2127                 :                : 
                               2128                 :            129 :         nss->input_count = 0;
                               2129                 :            129 :         nss->estimating = true;
                               2130                 :            129 :         initHyperLogLog(&nss->abbr_card, 10);
                               2131                 :                : 
                               2132                 :            129 :         ssup->ssup_extra = nss;
                               2133                 :                : 
                               2134                 :            129 :         ssup->abbrev_full_comparator = ssup->comparator;
                               2135                 :            129 :         ssup->comparator = numeric_cmp_abbrev;
                               2136                 :            129 :         ssup->abbrev_converter = numeric_abbrev_convert;
                               2137                 :            129 :         ssup->abbrev_abort = numeric_abbrev_abort;
                               2138                 :                : 
                               2139                 :            129 :         MemoryContextSwitchTo(oldcontext);
                               2140                 :                :     }
                               2141                 :                : 
                               2142                 :            570 :     PG_RETURN_VOID();
                               2143                 :                : }
                               2144                 :                : 
                               2145                 :                : /*
                               2146                 :                :  * Abbreviate a numeric datum, handling NaNs and detoasting
                               2147                 :                :  * (must not leak memory!)
                               2148                 :                :  */
                               2149                 :                : static Datum
                               2150                 :           9584 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
                               2151                 :                : {
                               2152                 :           9584 :     NumericSortSupport *nss = ssup->ssup_extra;
                               2153                 :           9584 :     void       *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
                               2154                 :                :     Numeric     value;
                               2155                 :                :     Datum       result;
                               2156                 :                : 
                               2157                 :           9584 :     nss->input_count += 1;
                               2158                 :                : 
                               2159                 :                :     /*
                               2160                 :                :      * This is to handle packed datums without needing a palloc/pfree cycle;
                               2161                 :                :      * we keep and reuse a buffer large enough to handle any short datum.
                               2162                 :                :      */
                               2163         [ +  + ]:           9584 :     if (VARATT_IS_SHORT(original_varatt))
                               2164                 :                :     {
                               2165                 :            513 :         void       *buf = nss->buf;
                               2166                 :            513 :         Size        sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
                               2167                 :                : 
                               2168         [ -  + ]:            513 :         Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
                               2169                 :                : 
                               2170                 :            513 :         SET_VARSIZE(buf, VARHDRSZ + sz);
                               2171                 :            513 :         memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
                               2172                 :                : 
                               2173                 :            513 :         value = (Numeric) buf;
                               2174                 :                :     }
                               2175                 :                :     else
                               2176                 :           9071 :         value = (Numeric) original_varatt;
                               2177                 :                : 
 1872 tgl@sss.pgh.pa.us        2178         [ +  + ]:           9584 :     if (NUMERIC_IS_SPECIAL(value))
                               2179                 :                :     {
                               2180         [ +  + ]:             75 :         if (NUMERIC_IS_PINF(value))
                               2181                 :             24 :             result = NUMERIC_ABBREV_PINF;
                               2182         [ +  + ]:             51 :         else if (NUMERIC_IS_NINF(value))
                               2183                 :             24 :             result = NUMERIC_ABBREV_NINF;
                               2184                 :                :         else
                               2185                 :             27 :             result = NUMERIC_ABBREV_NAN;
                               2186                 :                :     }
                               2187                 :                :     else
                               2188                 :                :     {
                               2189                 :                :         NumericVar  var;
                               2190                 :                : 
 3810 rhaas@postgresql.org     2191                 :           9509 :         init_var_from_num(value, &var);
                               2192                 :                : 
                               2193                 :           9509 :         result = numeric_abbrev_convert_var(&var, nss);
                               2194                 :                :     }
                               2195                 :                : 
                               2196                 :                :     /* should happen only for external/compressed toasts */
                               2197         [ -  + ]:           9584 :     if ((Pointer) original_varatt != DatumGetPointer(original_datum))
 3810 rhaas@postgresql.org     2198                 :UBC           0 :         pfree(original_varatt);
                               2199                 :                : 
 3810 rhaas@postgresql.org     2200                 :CBC        9584 :     return result;
                               2201                 :                : }
                               2202                 :                : 
                               2203                 :                : /*
                               2204                 :                :  * Consider whether to abort abbreviation.
                               2205                 :                :  *
                               2206                 :                :  * We pay no attention to the cardinality of the non-abbreviated data. There is
                               2207                 :                :  * no reason to do so: unlike text, we have no fast check for equal values, so
                               2208                 :                :  * we pay the full overhead whenever the abbreviations are equal regardless of
                               2209                 :                :  * whether the underlying values are also equal.
                               2210                 :                :  */
                               2211                 :                : static bool
                               2212                 :             72 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
                               2213                 :                : {
                               2214                 :             72 :     NumericSortSupport *nss = ssup->ssup_extra;
                               2215                 :                :     double      abbr_card;
                               2216                 :                : 
                               2217   [ -  +  -  -  :             72 :     if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
                                              -  - ]
                               2218                 :             72 :         return false;
                               2219                 :                : 
 3810 rhaas@postgresql.org     2220                 :UBC           0 :     abbr_card = estimateHyperLogLog(&nss->abbr_card);
                               2221                 :                : 
                               2222                 :                :     /*
                               2223                 :                :      * If we have >100k distinct values, then even if we were sorting many
                               2224                 :                :      * billion rows we'd likely still break even, and the penalty of undoing
                               2225                 :                :      * that many rows of abbrevs would probably not be worth it. Stop even
                               2226                 :                :      * counting at that point.
                               2227                 :                :      */
                               2228         [ #  # ]:              0 :     if (abbr_card > 100000.0)
                               2229                 :                :     {
                               2230         [ #  # ]:              0 :         if (trace_sort)
                               2231         [ #  # ]:              0 :             elog(LOG,
                               2232                 :                :                  "numeric_abbrev: estimation ends at cardinality %f"
                               2233                 :                :                  " after " INT64_FORMAT " values (%d rows)",
                               2234                 :                :                  abbr_card, nss->input_count, memtupcount);
                               2235                 :              0 :         nss->estimating = false;
                               2236                 :              0 :         return false;
                               2237                 :                :     }
                               2238                 :                : 
                               2239                 :                :     /*
                               2240                 :                :      * Target minimum cardinality is 1 per ~10k of non-null inputs.  (The
                               2241                 :                :      * break even point is somewhere between one per 100k rows, where
                               2242                 :                :      * abbreviation has a very slight penalty, and 1 per 10k where it wins by
                               2243                 :                :      * a measurable percentage.)  We use the relatively pessimistic 10k
                               2244                 :                :      * threshold, and add a 0.5 row fudge factor, because it allows us to
                               2245                 :                :      * abort earlier on genuinely pathological data where we've had exactly
                               2246                 :                :      * one abbreviated value in the first 10k (non-null) rows.
                               2247                 :                :      */
                               2248         [ #  # ]:              0 :     if (abbr_card < nss->input_count / 10000.0 + 0.5)
                               2249                 :                :     {
                               2250         [ #  # ]:              0 :         if (trace_sort)
                               2251         [ #  # ]:              0 :             elog(LOG,
                               2252                 :                :                  "numeric_abbrev: aborting abbreviation at cardinality %f"
                               2253                 :                :                  " below threshold %f after " INT64_FORMAT " values (%d rows)",
                               2254                 :                :                  abbr_card, nss->input_count / 10000.0 + 0.5,
                               2255                 :                :                  nss->input_count, memtupcount);
                               2256                 :              0 :         return true;
                               2257                 :                :     }
                               2258                 :                : 
                               2259         [ #  # ]:              0 :     if (trace_sort)
                               2260         [ #  # ]:              0 :         elog(LOG,
                               2261                 :                :              "numeric_abbrev: cardinality %f"
                               2262                 :                :              " after " INT64_FORMAT " values (%d rows)",
                               2263                 :                :              abbr_card, nss->input_count, memtupcount);
                               2264                 :                : 
                               2265                 :              0 :     return false;
                               2266                 :                : }
                               2267                 :                : 
                               2268                 :                : /*
                               2269                 :                :  * Non-fmgr interface to the comparison routine to allow sortsupport to elide
                               2270                 :                :  * the fmgr call.  The saving here is small given how slow numeric comparisons
                               2271                 :                :  * are, but it is a required part of the sort support API when abbreviations
                               2272                 :                :  * are performed.
                               2273                 :                :  *
                               2274                 :                :  * Two palloc/pfree cycles could be saved here by using persistent buffers for
                               2275                 :                :  * aligning short-varlena inputs, but this has not so far been considered to
                               2276                 :                :  * be worth the effort.
                               2277                 :                :  */
                               2278                 :                : static int
 3810 rhaas@postgresql.org     2279                 :CBC     8967283 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
                               2280                 :                : {
                               2281                 :        8967283 :     Numeric     nx = DatumGetNumeric(x);
                               2282                 :        8967283 :     Numeric     ny = DatumGetNumeric(y);
                               2283                 :                :     int         result;
                               2284                 :                : 
                               2285                 :        8967283 :     result = cmp_numerics(nx, ny);
                               2286                 :                : 
                               2287         [ +  + ]:        8967283 :     if ((Pointer) nx != DatumGetPointer(x))
                               2288                 :        2828085 :         pfree(nx);
                               2289         [ +  + ]:        8967283 :     if ((Pointer) ny != DatumGetPointer(y))
                               2290                 :        2828082 :         pfree(ny);
                               2291                 :                : 
                               2292                 :        8967283 :     return result;
                               2293                 :                : }
                               2294                 :                : 
                               2295                 :                : /*
                               2296                 :                :  * Compare abbreviations of values. (Abbreviations may be equal where the true
                               2297                 :                :  * values differ, but if the abbreviations differ, they must reflect the
                               2298                 :                :  * ordering of the true values.)
                               2299                 :                :  */
                               2300                 :                : static int
                               2301                 :          94982 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
                               2302                 :                : {
                               2303                 :                :     /*
                               2304                 :                :      * NOTE WELL: this is intentionally backwards, because the abbreviation is
                               2305                 :                :      * negated relative to the original value, to handle NaN/infinity cases.
                               2306                 :                :      */
                               2307         [ +  + ]:          94982 :     if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
                               2308                 :          50177 :         return 1;
                               2309         [ +  + ]:          44805 :     if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
                               2310                 :          44693 :         return -1;
                               2311                 :            112 :     return 0;
                               2312                 :                : }
                               2313                 :                : 
                               2314                 :                : /*
                               2315                 :                :  * Abbreviate a NumericVar into the 64-bit sortsupport size.
                               2316                 :                :  *
                               2317                 :                :  * The 31-bit value is constructed as:
                               2318                 :                :  *
                               2319                 :                :  *  0 + 7bits digit weight + 24 bits digit value
                               2320                 :                :  *
                               2321                 :                :  * where the digit weight is in single decimal digits, not digit words, and
                               2322                 :                :  * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
                               2323                 :                :  * significant decimal digits of the value converted to binary. Values whose
                               2324                 :                :  * weights would fall outside the representable range are rounded off to zero
                               2325                 :                :  * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
                               2326                 :                :  * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
                               2327                 :                :  * where values are outside the range 10^-44 to 10^83, which is not considered
                               2328                 :                :  * to be a serious limitation, or when values are of the same magnitude and
                               2329                 :                :  * equal in the first 7 decimal digits, which is considered to be an
                               2330                 :                :  * unavoidable limitation given the available bits. (Stealing three more bits
                               2331                 :                :  * to compare another digit would narrow the range of representable weights by
                               2332                 :                :  * a factor of 8, which starts to look like a real limiting factor.)
                               2333                 :                :  *
                               2334                 :                :  * (The value 44 for the excess is essentially arbitrary)
                               2335                 :                :  *
                               2336                 :                :  * The 63-bit value is constructed as:
                               2337                 :                :  *
                               2338                 :                :  *  0 + 7bits weight + 4 x 14-bit packed digit words
                               2339                 :                :  *
                               2340                 :                :  * The weight in this case is again stored in excess-44, but this time it is
                               2341                 :                :  * the original weight in digit words (i.e. powers of 10000). The first four
                               2342                 :                :  * digit words of the value (if present; trailing zeros are assumed as needed)
                               2343                 :                :  * are packed into 14 bits each to form the rest of the value. Again,
                               2344                 :                :  * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
                               2345                 :                :  * representable range in this case is 10^-176 to 10^332, which is considered
                               2346                 :                :  * to be good enough for all practical purposes, and comparison of 4 words
                               2347                 :                :  * means that at least 13 decimal digits are compared, which is considered to
                               2348                 :                :  * be a reasonable compromise between effectiveness and efficiency in computing
                               2349                 :                :  * the abbreviation.
                               2350                 :                :  *
                               2351                 :                :  * (The value 44 for the excess is even more arbitrary here, it was chosen just
                               2352                 :                :  * to match the value used in the 31-bit case)
                               2353                 :                :  *
                               2354                 :                :  * [1] - Excess-k representation means that the value is offset by adding 'k'
                               2355                 :                :  * and then treated as unsigned, so the smallest representable value is stored
                               2356                 :                :  * with all bits zero. This allows simple comparisons to work on the composite
                               2357                 :                :  * value.
                               2358                 :                :  */
                               2359                 :                : static Datum
 2918 andres@anarazel.de       2360                 :           9509 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
                               2361                 :                : {
 3810 rhaas@postgresql.org     2362                 :           9509 :     int         ndigits = var->ndigits;
                               2363                 :           9509 :     int         weight = var->weight;
                               2364                 :                :     int64       result;
                               2365                 :                : 
                               2366   [ +  +  -  + ]:           9509 :     if (ndigits == 0 || weight < -44)
                               2367                 :                :     {
                               2368                 :             27 :         result = 0;
                               2369                 :                :     }
                               2370         [ +  + ]:           9482 :     else if (weight > 83)
                               2371                 :                :     {
                               2372                 :              6 :         result = PG_INT64_MAX;
                               2373                 :                :     }
                               2374                 :                :     else
                               2375                 :                :     {
                               2376                 :           9476 :         result = ((int64) (weight + 44) << 56);
                               2377                 :                : 
                               2378   [ -  +  +  + ]:           9476 :         switch (ndigits)
                               2379                 :                :         {
 3810 rhaas@postgresql.org     2380                 :UBC           0 :             default:
                               2381                 :              0 :                 result |= ((int64) var->digits[3]);
                               2382                 :                :                 /* FALLTHROUGH */
 3810 rhaas@postgresql.org     2383                 :CBC        3104 :             case 3:
                               2384                 :           3104 :                 result |= ((int64) var->digits[2]) << 14;
                               2385                 :                :                 /* FALLTHROUGH */
                               2386                 :           9155 :             case 2:
                               2387                 :           9155 :                 result |= ((int64) var->digits[1]) << 28;
                               2388                 :                :                 /* FALLTHROUGH */
                               2389                 :           9476 :             case 1:
                               2390                 :           9476 :                 result |= ((int64) var->digits[0]) << 42;
                               2391                 :           9476 :                 break;
                               2392                 :                :         }
                               2393                 :                :     }
                               2394                 :                : 
                               2395                 :                :     /* the abbrev is negated relative to the original */
                               2396         [ +  + ]:           9509 :     if (var->sign == NUMERIC_POS)
                               2397                 :           9460 :         result = -result;
                               2398                 :                : 
                               2399         [ +  - ]:           9509 :     if (nss->estimating)
                               2400                 :                :     {
                               2401                 :           9509 :         uint32      tmp = ((uint32) result
                               2402                 :           9509 :                            ^ (uint32) ((uint64) result >> 32));
                               2403                 :                : 
                               2404                 :           9509 :         addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
                               2405                 :                :     }
                               2406                 :                : 
 3809                          2407                 :           9509 :     return NumericAbbrevGetDatum(result);
                               2408                 :                : }
                               2409                 :                : 
                               2410                 :                : 
                               2411                 :                : /*
                               2412                 :                :  * Ordinary (non-sortsupport) comparisons follow.
                               2413                 :                :  */
                               2414                 :                : 
                               2415                 :                : Datum
 9170 tgl@sss.pgh.pa.us        2416                 :         467484 : numeric_cmp(PG_FUNCTION_ARGS)
                               2417                 :                : {
                               2418                 :         467484 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2419                 :         467484 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2420                 :                :     int         result;
                               2421                 :                : 
 8892                          2422                 :         467484 :     result = cmp_numerics(num1, num2);
                               2423                 :                : 
 9170                          2424         [ +  + ]:         467484 :     PG_FREE_IF_COPY(num1, 0);
                               2425         [ +  + ]:         467484 :     PG_FREE_IF_COPY(num2, 1);
                               2426                 :                : 
                               2427                 :         467484 :     PG_RETURN_INT32(result);
                               2428                 :                : }
                               2429                 :                : 
                               2430                 :                : 
                               2431                 :                : Datum
                               2432                 :         341076 : numeric_eq(PG_FUNCTION_ARGS)
                               2433                 :                : {
                               2434                 :         341076 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2435                 :         341076 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2436                 :                :     bool        result;
                               2437                 :                : 
 8892                          2438                 :         341076 :     result = cmp_numerics(num1, num2) == 0;
                               2439                 :                : 
 9170                          2440         [ +  + ]:         341076 :     PG_FREE_IF_COPY(num1, 0);
                               2441         [ +  + ]:         341076 :     PG_FREE_IF_COPY(num2, 1);
                               2442                 :                : 
                               2443                 :         341076 :     PG_RETURN_BOOL(result);
                               2444                 :                : }
                               2445                 :                : 
                               2446                 :                : Datum
                               2447                 :           2688 : numeric_ne(PG_FUNCTION_ARGS)
                               2448                 :                : {
                               2449                 :           2688 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2450                 :           2688 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2451                 :                :     bool        result;
                               2452                 :                : 
 8892                          2453                 :           2688 :     result = cmp_numerics(num1, num2) != 0;
                               2454                 :                : 
 9170                          2455         [ +  + ]:           2688 :     PG_FREE_IF_COPY(num1, 0);
                               2456         [ +  + ]:           2688 :     PG_FREE_IF_COPY(num2, 1);
                               2457                 :                : 
                               2458                 :           2688 :     PG_RETURN_BOOL(result);
                               2459                 :                : }
                               2460                 :                : 
                               2461                 :                : Datum
                               2462                 :          27801 : numeric_gt(PG_FUNCTION_ARGS)
                               2463                 :                : {
                               2464                 :          27801 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2465                 :          27801 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2466                 :                :     bool        result;
                               2467                 :                : 
 8892                          2468                 :          27801 :     result = cmp_numerics(num1, num2) > 0;
                               2469                 :                : 
 9170                          2470         [ +  + ]:          27801 :     PG_FREE_IF_COPY(num1, 0);
                               2471         [ +  + ]:          27801 :     PG_FREE_IF_COPY(num2, 1);
                               2472                 :                : 
                               2473                 :          27801 :     PG_RETURN_BOOL(result);
                               2474                 :                : }
                               2475                 :                : 
                               2476                 :                : Datum
                               2477                 :           7507 : numeric_ge(PG_FUNCTION_ARGS)
                               2478                 :                : {
                               2479                 :           7507 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2480                 :           7507 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2481                 :                :     bool        result;
                               2482                 :                : 
 8892                          2483                 :           7507 :     result = cmp_numerics(num1, num2) >= 0;
                               2484                 :                : 
 9170                          2485         [ +  + ]:           7507 :     PG_FREE_IF_COPY(num1, 0);
                               2486         [ -  + ]:           7507 :     PG_FREE_IF_COPY(num2, 1);
                               2487                 :                : 
                               2488                 :           7507 :     PG_RETURN_BOOL(result);
                               2489                 :                : }
                               2490                 :                : 
                               2491                 :                : Datum
                               2492                 :          68573 : numeric_lt(PG_FUNCTION_ARGS)
                               2493                 :                : {
                               2494                 :          68573 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2495                 :          68573 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2496                 :                :     bool        result;
                               2497                 :                : 
 8892                          2498                 :          68573 :     result = cmp_numerics(num1, num2) < 0;
                               2499                 :                : 
 9170                          2500         [ +  + ]:          68573 :     PG_FREE_IF_COPY(num1, 0);
                               2501         [ +  + ]:          68573 :     PG_FREE_IF_COPY(num2, 1);
                               2502                 :                : 
                               2503                 :          68573 :     PG_RETURN_BOOL(result);
                               2504                 :                : }
                               2505                 :                : 
                               2506                 :                : Datum
                               2507                 :           8963 : numeric_le(PG_FUNCTION_ARGS)
                               2508                 :                : {
                               2509                 :           8963 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2510                 :           8963 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2511                 :                :     bool        result;
                               2512                 :                : 
 8892                          2513                 :           8963 :     result = cmp_numerics(num1, num2) <= 0;
                               2514                 :                : 
                               2515         [ +  + ]:           8963 :     PG_FREE_IF_COPY(num1, 0);
                               2516         [ +  + ]:           8963 :     PG_FREE_IF_COPY(num2, 1);
                               2517                 :                : 
                               2518                 :           8963 :     PG_RETURN_BOOL(result);
                               2519                 :                : }
                               2520                 :                : 
                               2521                 :                : static int
                               2522                 :        9902145 : cmp_numerics(Numeric num1, Numeric num2)
                               2523                 :                : {
                               2524                 :                :     int         result;
                               2525                 :                : 
                               2526                 :                :     /*
                               2527                 :                :      * We consider all NANs to be equal and larger than any non-NAN (including
                               2528                 :                :      * Infinity).  This is somewhat arbitrary; the important thing is to have
                               2529                 :                :      * a consistent sort order.
                               2530                 :                :      */
 1872                          2531         [ +  + ]:        9902145 :     if (NUMERIC_IS_SPECIAL(num1))
                               2532                 :                :     {
                               2533         [ +  + ]:           3275 :         if (NUMERIC_IS_NAN(num1))
                               2534                 :                :         {
                               2535         [ +  + ]:           3230 :             if (NUMERIC_IS_NAN(num2))
                               2536                 :            456 :                 result = 0;     /* NAN = NAN */
                               2537                 :                :             else
                               2538                 :           2774 :                 result = 1;     /* NAN > non-NAN */
                               2539                 :                :         }
                               2540         [ +  + ]:             45 :         else if (NUMERIC_IS_PINF(num1))
                               2541                 :                :         {
                               2542         [ -  + ]:             36 :             if (NUMERIC_IS_NAN(num2))
 1872 tgl@sss.pgh.pa.us        2543                 :UBC           0 :                 result = -1;    /* PINF < NAN */
 1872 tgl@sss.pgh.pa.us        2544         [ +  + ]:CBC          36 :             else if (NUMERIC_IS_PINF(num2))
                               2545                 :              3 :                 result = 0;     /* PINF = PINF */
                               2546                 :                :             else
                               2547                 :             33 :                 result = 1;     /* PINF > anything else */
                               2548                 :                :         }
                               2549                 :                :         else                    /* num1 must be NINF */
                               2550                 :                :         {
                               2551         [ +  + ]:              9 :             if (NUMERIC_IS_NINF(num2))
                               2552                 :              3 :                 result = 0;     /* NINF = NINF */
                               2553                 :                :             else
                               2554                 :              6 :                 result = -1;    /* NINF < anything else */
                               2555                 :                :         }
                               2556                 :                :     }
                               2557         [ +  + ]:        9898870 :     else if (NUMERIC_IS_SPECIAL(num2))
                               2558                 :                :     {
                               2559         [ +  + ]:           5585 :         if (NUMERIC_IS_NINF(num2))
                               2560                 :              6 :             result = 1;         /* normal > NINF */
                               2561                 :                :         else
                               2562                 :           5579 :             result = -1;        /* normal < NAN or PINF */
                               2563                 :                :     }
                               2564                 :                :     else
                               2565                 :                :     {
 7151 bruce@momjian.us         2566   [ +  +  +  + ]:       19787084 :         result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
 5513 rhaas@postgresql.org     2567   [ +  +  -  +  :        9893436 :                                 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
                                        +  +  +  + ]
 7151 bruce@momjian.us         2568   [ +  +  +  + ]:        9893285 :                                 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
 5513 rhaas@postgresql.org     2569   [ +  +  -  +  :        9893648 :                                 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
                                        +  +  +  + ]
                               2570                 :                :     }
                               2571                 :                : 
 8892 tgl@sss.pgh.pa.us        2572                 :        9902145 :     return result;
                               2573                 :                : }
                               2574                 :                : 
                               2575                 :                : /*
                               2576                 :                :  * in_range support function for numeric.
                               2577                 :                :  */
                               2578                 :                : Datum
 2751                          2579                 :            576 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
                               2580                 :                : {
                               2581                 :            576 :     Numeric     val = PG_GETARG_NUMERIC(0);
                               2582                 :            576 :     Numeric     base = PG_GETARG_NUMERIC(1);
                               2583                 :            576 :     Numeric     offset = PG_GETARG_NUMERIC(2);
                               2584                 :            576 :     bool        sub = PG_GETARG_BOOL(3);
                               2585                 :            576 :     bool        less = PG_GETARG_BOOL(4);
                               2586                 :                :     bool        result;
                               2587                 :                : 
                               2588                 :                :     /*
                               2589                 :                :      * Reject negative (including -Inf) or NaN offset.  Negative is per spec,
                               2590                 :                :      * and NaN is because appropriate semantics for that seem non-obvious.
                               2591                 :                :      */
 1872                          2592         [ +  + ]:            576 :     if (NUMERIC_IS_NAN(offset) ||
                               2593         [ +  - ]:            573 :         NUMERIC_IS_NINF(offset) ||
                               2594   [ +  +  -  +  :            573 :         NUMERIC_SIGN(offset) == NUMERIC_NEG)
                                     +  -  -  +  -  
                                                 - ]
 2751                          2595         [ +  - ]:              3 :         ereport(ERROR,
                               2596                 :                :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
                               2597                 :                :                  errmsg("invalid preceding or following size in window function")));
                               2598                 :                : 
                               2599                 :                :     /*
                               2600                 :                :      * Deal with cases where val and/or base is NaN, following the rule that
                               2601                 :                :      * NaN sorts after non-NaN (cf cmp_numerics).  The offset cannot affect
                               2602                 :                :      * the conclusion.
                               2603                 :                :      */
                               2604         [ +  + ]:            573 :     if (NUMERIC_IS_NAN(val))
                               2605                 :                :     {
                               2606         [ +  + ]:             93 :         if (NUMERIC_IS_NAN(base))
                               2607                 :             30 :             result = true;      /* NAN = NAN */
                               2608                 :                :         else
                               2609                 :             63 :             result = !less;     /* NAN > non-NAN */
                               2610                 :                :     }
                               2611         [ +  + ]:            480 :     else if (NUMERIC_IS_NAN(base))
                               2612                 :                :     {
                               2613                 :             63 :         result = less;          /* non-NAN < NAN */
                               2614                 :                :     }
                               2615                 :                : 
                               2616                 :                :     /*
                               2617                 :                :      * Deal with infinite offset (necessarily +Inf, at this point).
                               2618                 :                :      */
 1872                          2619         [ +  + ]:            417 :     else if (NUMERIC_IS_SPECIAL(offset))
                               2620                 :                :     {
                               2621         [ -  + ]:            210 :         Assert(NUMERIC_IS_PINF(offset));
                               2622   [ +  +  +  + ]:            210 :         if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
                               2623                 :                :         {
                               2624                 :                :             /*
                               2625                 :                :              * base +/- offset would produce NaN, so return true for any val
                               2626                 :                :              * (see in_range_float8_float8() for reasoning).
                               2627                 :                :              */
                               2628                 :             87 :             result = true;
                               2629                 :                :         }
                               2630         [ +  + ]:            123 :         else if (sub)
                               2631                 :                :         {
                               2632                 :                :             /* base - offset must be -inf */
                               2633         [ +  + ]:             75 :             if (less)
                               2634                 :             27 :                 result = NUMERIC_IS_NINF(val);  /* only -inf is <= sum */
                               2635                 :                :             else
                               2636                 :             48 :                 result = true;  /* any val is >= sum */
                               2637                 :                :         }
                               2638                 :                :         else
                               2639                 :                :         {
                               2640                 :                :             /* base + offset must be +inf */
                               2641         [ -  + ]:             48 :             if (less)
 1872 tgl@sss.pgh.pa.us        2642                 :UBC           0 :                 result = true;  /* any val is <= sum */
                               2643                 :                :             else
 1872 tgl@sss.pgh.pa.us        2644                 :CBC          48 :                 result = NUMERIC_IS_PINF(val);  /* only +inf is >= sum */
                               2645                 :                :         }
                               2646                 :                :     }
                               2647                 :                : 
                               2648                 :                :     /*
                               2649                 :                :      * Deal with cases where val and/or base is infinite.  The offset, being
                               2650                 :                :      * now known finite, cannot affect the conclusion.
                               2651                 :                :      */
                               2652         [ +  + ]:            207 :     else if (NUMERIC_IS_SPECIAL(val))
                               2653                 :                :     {
                               2654         [ +  + ]:             39 :         if (NUMERIC_IS_PINF(val))
                               2655                 :                :         {
                               2656         [ +  + ]:             18 :             if (NUMERIC_IS_PINF(base))
                               2657                 :             12 :                 result = true;  /* PINF = PINF */
                               2658                 :                :             else
                               2659                 :              6 :                 result = !less; /* PINF > any other non-NAN */
                               2660                 :                :         }
                               2661                 :                :         else                    /* val must be NINF */
                               2662                 :                :         {
                               2663         [ +  + ]:             21 :             if (NUMERIC_IS_NINF(base))
                               2664                 :             15 :                 result = true;  /* NINF = NINF */
                               2665                 :                :             else
                               2666                 :              6 :                 result = less;  /* NINF < anything else */
                               2667                 :                :         }
                               2668                 :                :     }
                               2669         [ +  + ]:            168 :     else if (NUMERIC_IS_SPECIAL(base))
                               2670                 :                :     {
                               2671         [ +  + ]:             12 :         if (NUMERIC_IS_NINF(base))
                               2672                 :              6 :             result = !less;     /* normal > NINF */
                               2673                 :                :         else
                               2674                 :              6 :             result = less;      /* normal < PINF */
                               2675                 :                :     }
                               2676                 :                :     else
                               2677                 :                :     {
                               2678                 :                :         /*
                               2679                 :                :          * Otherwise go ahead and compute base +/- offset.  While it's
                               2680                 :                :          * possible for this to overflow the numeric format, it's unlikely
                               2681                 :                :          * enough that we don't take measures to prevent it.
                               2682                 :                :          */
                               2683                 :                :         NumericVar  valv;
                               2684                 :                :         NumericVar  basev;
                               2685                 :                :         NumericVar  offsetv;
                               2686                 :                :         NumericVar  sum;
                               2687                 :                : 
 2751                          2688                 :            156 :         init_var_from_num(val, &valv);
                               2689                 :            156 :         init_var_from_num(base, &basev);
                               2690                 :            156 :         init_var_from_num(offset, &offsetv);
                               2691                 :            156 :         init_var(&sum);
                               2692                 :                : 
                               2693         [ +  + ]:            156 :         if (sub)
                               2694                 :             78 :             sub_var(&basev, &offsetv, &sum);
                               2695                 :                :         else
                               2696                 :             78 :             add_var(&basev, &offsetv, &sum);
                               2697                 :                : 
                               2698         [ +  + ]:            156 :         if (less)
                               2699                 :             78 :             result = (cmp_var(&valv, &sum) <= 0);
                               2700                 :                :         else
                               2701                 :             78 :             result = (cmp_var(&valv, &sum) >= 0);
                               2702                 :                : 
                               2703                 :            156 :         free_var(&sum);
                               2704                 :                :     }
                               2705                 :                : 
                               2706         [ +  - ]:            573 :     PG_FREE_IF_COPY(val, 0);
                               2707         [ +  - ]:            573 :     PG_FREE_IF_COPY(base, 1);
                               2708         [ -  + ]:            573 :     PG_FREE_IF_COPY(offset, 2);
                               2709                 :                : 
                               2710                 :            573 :     PG_RETURN_BOOL(result);
                               2711                 :                : }
                               2712                 :                : 
                               2713                 :                : Datum
 6696 neilc@samurai.com        2714                 :         303772 : hash_numeric(PG_FUNCTION_ARGS)
                               2715                 :                : {
 6505 bruce@momjian.us         2716                 :         303772 :     Numeric     key = PG_GETARG_NUMERIC(0);
                               2717                 :                :     Datum       digit_hash;
                               2718                 :                :     Datum       result;
                               2719                 :                :     int         weight;
                               2720                 :                :     int         start_offset;
                               2721                 :                :     int         end_offset;
                               2722                 :                :     int         i;
                               2723                 :                :     int         hash_len;
                               2724                 :                :     NumericDigit *digits;
                               2725                 :                : 
                               2726                 :                :     /* If it's NaN or infinity, don't try to hash the rest of the fields */
 1872 tgl@sss.pgh.pa.us        2727         [ -  + ]:         303772 :     if (NUMERIC_IS_SPECIAL(key))
 6696 neilc@samurai.com        2728                 :UBC           0 :         PG_RETURN_UINT32(0);
                               2729                 :                : 
 5513 rhaas@postgresql.org     2730   [ +  -  +  + ]:CBC      303772 :     weight = NUMERIC_WEIGHT(key);
 6696 neilc@samurai.com        2731                 :         303772 :     start_offset = 0;
 6505 bruce@momjian.us         2732                 :         303772 :     end_offset = 0;
                               2733                 :                : 
                               2734                 :                :     /*
                               2735                 :                :      * Omit any leading or trailing zeros from the input to the hash. The
                               2736                 :                :      * numeric implementation *should* guarantee that leading and trailing
                               2737                 :                :      * zeros are suppressed, but we're paranoid. Note that we measure the
                               2738                 :                :      * starting and ending offsets in units of NumericDigits, not bytes.
                               2739                 :                :      */
 5513 rhaas@postgresql.org     2740         [ +  - ]:         303772 :     digits = NUMERIC_DIGITS(key);
 6696 neilc@samurai.com        2741   [ +  -  +  + ]:         303772 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
                               2742                 :                :     {
 5513 rhaas@postgresql.org     2743         [ +  - ]:         302946 :         if (digits[i] != (NumericDigit) 0)
 6696 neilc@samurai.com        2744                 :         302946 :             break;
                               2745                 :                : 
 6696 neilc@samurai.com        2746                 :UBC           0 :         start_offset++;
                               2747                 :                : 
                               2748                 :                :         /*
                               2749                 :                :          * The weight is effectively the # of digits before the decimal point,
                               2750                 :                :          * so decrement it for each leading zero we skip.
                               2751                 :                :          */
                               2752                 :              0 :         weight--;
                               2753                 :                :     }
                               2754                 :                : 
                               2755                 :                :     /*
                               2756                 :                :      * If there are no non-zero digits, then the value of the number is zero,
                               2757                 :                :      * regardless of any other fields.
                               2758                 :                :      */
 6696 neilc@samurai.com        2759   [ +  -  +  + ]:CBC      303772 :     if (NUMERIC_NDIGITS(key) == start_offset)
                               2760                 :            826 :         PG_RETURN_UINT32(-1);
                               2761                 :                : 
                               2762   [ +  -  +  - ]:         302946 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
                               2763                 :                :     {
 5513 rhaas@postgresql.org     2764         [ +  - ]:         302946 :         if (digits[i] != (NumericDigit) 0)
 6696 neilc@samurai.com        2765                 :         302946 :             break;
                               2766                 :                : 
 6696 neilc@samurai.com        2767                 :UBC           0 :         end_offset++;
                               2768                 :                :     }
                               2769                 :                : 
                               2770                 :                :     /* If we get here, there should be at least one non-zero digit */
 6696 neilc@samurai.com        2771   [ +  -  -  + ]:CBC      302946 :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
                               2772                 :                : 
                               2773                 :                :     /*
                               2774                 :                :      * Note that we don't hash on the Numeric's scale, since two numerics can
                               2775                 :                :      * compare equal but have different scales. We also don't hash on the
                               2776                 :                :      * sign, although we could: since a sign difference implies inequality,
                               2777                 :                :      * this shouldn't affect correctness.
                               2778                 :                :      */
                               2779         [ +  - ]:         302946 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
                               2780         [ +  - ]:         302946 :     digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
                               2781                 :                :                           hash_len * sizeof(NumericDigit));
                               2782                 :                : 
                               2783                 :                :     /* Mix in the weight, via XOR */
                               2784                 :         302946 :     result = digit_hash ^ weight;
                               2785                 :                : 
                               2786                 :         302946 :     PG_RETURN_DATUM(result);
                               2787                 :                : }
                               2788                 :                : 
                               2789                 :                : /*
                               2790                 :                :  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
                               2791                 :                :  * Otherwise, similar to hash_numeric.
                               2792                 :                :  */
                               2793                 :                : Datum
 2928 rhaas@postgresql.org     2794                 :             42 : hash_numeric_extended(PG_FUNCTION_ARGS)
                               2795                 :                : {
                               2796                 :             42 :     Numeric     key = PG_GETARG_NUMERIC(0);
                               2797                 :             42 :     uint64      seed = PG_GETARG_INT64(1);
                               2798                 :                :     Datum       digit_hash;
                               2799                 :                :     Datum       result;
                               2800                 :                :     int         weight;
                               2801                 :                :     int         start_offset;
                               2802                 :                :     int         end_offset;
                               2803                 :                :     int         i;
                               2804                 :                :     int         hash_len;
                               2805                 :                :     NumericDigit *digits;
                               2806                 :                : 
                               2807                 :                :     /* If it's NaN or infinity, don't try to hash the rest of the fields */
 1872 tgl@sss.pgh.pa.us        2808         [ -  + ]:             42 :     if (NUMERIC_IS_SPECIAL(key))
 2928 rhaas@postgresql.org     2809                 :UBC           0 :         PG_RETURN_UINT64(seed);
                               2810                 :                : 
 2928 rhaas@postgresql.org     2811   [ +  -  -  + ]:CBC          42 :     weight = NUMERIC_WEIGHT(key);
                               2812                 :             42 :     start_offset = 0;
                               2813                 :             42 :     end_offset = 0;
                               2814                 :                : 
                               2815         [ +  - ]:             42 :     digits = NUMERIC_DIGITS(key);
                               2816   [ +  -  +  + ]:             42 :     for (i = 0; i < NUMERIC_NDIGITS(key); i++)
                               2817                 :                :     {
                               2818         [ +  - ]:             36 :         if (digits[i] != (NumericDigit) 0)
                               2819                 :             36 :             break;
                               2820                 :                : 
 2928 rhaas@postgresql.org     2821                 :UBC           0 :         start_offset++;
                               2822                 :                : 
                               2823                 :              0 :         weight--;
                               2824                 :                :     }
                               2825                 :                : 
 2928 rhaas@postgresql.org     2826   [ +  -  +  + ]:CBC          42 :     if (NUMERIC_NDIGITS(key) == start_offset)
                               2827                 :              6 :         PG_RETURN_UINT64(seed - 1);
                               2828                 :                : 
                               2829   [ +  -  +  - ]:             36 :     for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
                               2830                 :                :     {
                               2831         [ +  - ]:             36 :         if (digits[i] != (NumericDigit) 0)
                               2832                 :             36 :             break;
                               2833                 :                : 
 2928 rhaas@postgresql.org     2834                 :UBC           0 :         end_offset++;
                               2835                 :                :     }
                               2836                 :                : 
 2928 rhaas@postgresql.org     2837   [ +  -  -  + ]:CBC          36 :     Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
                               2838                 :                : 
                               2839         [ +  - ]:             36 :     hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
                               2840         [ +  - ]:             36 :     digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
                               2841                 :             36 :                                                       + start_offset),
                               2842                 :                :                                    hash_len * sizeof(NumericDigit),
                               2843                 :                :                                    seed);
                               2844                 :                : 
 2927                          2845                 :             36 :     result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
                               2846                 :                : 
 2928                          2847                 :             36 :     PG_RETURN_DATUM(result);
                               2848                 :                : }
                               2849                 :                : 
                               2850                 :                : 
                               2851                 :                : /* ----------------------------------------------------------------------
                               2852                 :                :  *
                               2853                 :                :  * Basic arithmetic functions
                               2854                 :                :  *
                               2855                 :                :  * ----------------------------------------------------------------------
                               2856                 :                :  */
                               2857                 :                : 
                               2858                 :                : 
                               2859                 :                : /*
                               2860                 :                :  * numeric_add() -
                               2861                 :                :  *
                               2862                 :                :  *  Add two numerics
                               2863                 :                :  */
                               2864                 :                : Datum
 9170 tgl@sss.pgh.pa.us        2865                 :         126092 : numeric_add(PG_FUNCTION_ARGS)
                               2866                 :                : {
                               2867                 :         126092 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2868                 :         126092 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2869                 :                :     Numeric     res;
                               2870                 :                : 
    1 michael@paquier.xyz      2871                 :GNC      126092 :     res = numeric_add_safe(num1, num2, NULL);
                               2872                 :                : 
 2366 akorotkov@postgresql     2873                 :CBC      126092 :     PG_RETURN_NUMERIC(res);
                               2874                 :                : }
                               2875                 :                : 
                               2876                 :                : /*
                               2877                 :                :  * numeric_add_safe() -
                               2878                 :                :  *
                               2879                 :                :  *  Internal version of numeric_add() with support for soft error reporting.
                               2880                 :                :  */
                               2881                 :                : Numeric
    1 michael@paquier.xyz      2882                 :GNC      126611 : numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
                               2883                 :                : {
                               2884                 :                :     NumericVar  arg1;
                               2885                 :                :     NumericVar  arg2;
                               2886                 :                :     NumericVar  result;
                               2887                 :                :     Numeric     res;
                               2888                 :                : 
                               2889                 :                :     /*
                               2890                 :                :      * Handle NaN and infinities
                               2891                 :                :      */
 1872 tgl@sss.pgh.pa.us        2892   [ +  +  +  + ]:CBC      126611 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               2893                 :                :     {
                               2894   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               2895                 :             39 :             return make_result(&const_nan);
                               2896         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               2897                 :                :         {
                               2898         [ +  + ]:             18 :             if (NUMERIC_IS_NINF(num2))
                               2899                 :              3 :                 return make_result(&const_nan); /* Inf + -Inf */
                               2900                 :                :             else
                               2901                 :             15 :                 return make_result(&const_pinf);
                               2902                 :                :         }
                               2903         [ +  + ]:             42 :         if (NUMERIC_IS_NINF(num1))
                               2904                 :                :         {
                               2905         [ +  + ]:             18 :             if (NUMERIC_IS_PINF(num2))
                               2906                 :              3 :                 return make_result(&const_nan); /* -Inf + Inf */
                               2907                 :                :             else
                               2908                 :             15 :                 return make_result(&const_ninf);
                               2909                 :                :         }
                               2910                 :                :         /* by here, num1 must be finite, so num2 is not */
                               2911         [ +  + ]:             24 :         if (NUMERIC_IS_PINF(num2))
                               2912                 :             12 :             return make_result(&const_pinf);
                               2913         [ -  + ]:             12 :         Assert(NUMERIC_IS_NINF(num2));
                               2914                 :             12 :         return make_result(&const_ninf);
                               2915                 :                :     }
                               2916                 :                : 
                               2917                 :                :     /*
                               2918                 :                :      * Unpack the values, let add_var() compute the result and return it.
                               2919                 :                :      */
 4672 heikki.linnakangas@i     2920                 :         126512 :     init_var_from_num(num1, &arg1);
                               2921                 :         126512 :     init_var_from_num(num2, &arg2);
                               2922                 :                : 
                               2923                 :         126512 :     init_var(&result);
 9747 JanWieck@Yahoo.com       2924                 :         126512 :     add_var(&arg1, &arg2, &result);
                               2925                 :                : 
    1 michael@paquier.xyz      2926                 :GNC      126512 :     res = make_result_safe(&result, escontext);
                               2927                 :                : 
 9747 JanWieck@Yahoo.com       2928                 :CBC      126512 :     free_var(&result);
                               2929                 :                : 
 2366 akorotkov@postgresql     2930                 :         126512 :     return res;
                               2931                 :                : }
                               2932                 :                : 
                               2933                 :                : 
                               2934                 :                : /*
                               2935                 :                :  * numeric_sub() -
                               2936                 :                :  *
                               2937                 :                :  *  Subtract one numeric from another
                               2938                 :                :  */
                               2939                 :                : Datum
 9170 tgl@sss.pgh.pa.us        2940                 :          37698 : numeric_sub(PG_FUNCTION_ARGS)
                               2941                 :                : {
                               2942                 :          37698 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               2943                 :          37698 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               2944                 :                :     Numeric     res;
                               2945                 :                : 
    1 michael@paquier.xyz      2946                 :GNC       37698 :     res = numeric_sub_safe(num1, num2, NULL);
                               2947                 :                : 
 2366 akorotkov@postgresql     2948                 :CBC       37698 :     PG_RETURN_NUMERIC(res);
                               2949                 :                : }
                               2950                 :                : 
                               2951                 :                : 
                               2952                 :                : /*
                               2953                 :                :  * numeric_sub_safe() -
                               2954                 :                :  *
                               2955                 :                :  *  Internal version of numeric_sub() with support for soft error reporting.
                               2956                 :                :  */
                               2957                 :                : Numeric
    1 michael@paquier.xyz      2958                 :GNC       37773 : numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
                               2959                 :                : {
                               2960                 :                :     NumericVar  arg1;
                               2961                 :                :     NumericVar  arg2;
                               2962                 :                :     NumericVar  result;
                               2963                 :                :     Numeric     res;
                               2964                 :                : 
                               2965                 :                :     /*
                               2966                 :                :      * Handle NaN and infinities
                               2967                 :                :      */
 1872 tgl@sss.pgh.pa.us        2968   [ +  +  +  + ]:CBC       37773 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               2969                 :                :     {
                               2970   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               2971                 :             39 :             return make_result(&const_nan);
                               2972         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               2973                 :                :         {
                               2974         [ +  + ]:             18 :             if (NUMERIC_IS_PINF(num2))
                               2975                 :              3 :                 return make_result(&const_nan); /* Inf - Inf */
                               2976                 :                :             else
                               2977                 :             15 :                 return make_result(&const_pinf);
                               2978                 :                :         }
                               2979         [ +  + ]:             42 :         if (NUMERIC_IS_NINF(num1))
                               2980                 :                :         {
                               2981         [ +  + ]:             18 :             if (NUMERIC_IS_NINF(num2))
                               2982                 :              3 :                 return make_result(&const_nan); /* -Inf - -Inf */
                               2983                 :                :             else
                               2984                 :             15 :                 return make_result(&const_ninf);
                               2985                 :                :         }
                               2986                 :                :         /* by here, num1 must be finite, so num2 is not */
                               2987         [ +  + ]:             24 :         if (NUMERIC_IS_PINF(num2))
                               2988                 :             12 :             return make_result(&const_ninf);
                               2989         [ -  + ]:             12 :         Assert(NUMERIC_IS_NINF(num2));
                               2990                 :             12 :         return make_result(&const_pinf);
                               2991                 :                :     }
                               2992                 :                : 
                               2993                 :                :     /*
                               2994                 :                :      * Unpack the values, let sub_var() compute the result and return it.
                               2995                 :                :      */
 4672 heikki.linnakangas@i     2996                 :          37674 :     init_var_from_num(num1, &arg1);
                               2997                 :          37674 :     init_var_from_num(num2, &arg2);
                               2998                 :                : 
                               2999                 :          37674 :     init_var(&result);
 9747 JanWieck@Yahoo.com       3000                 :          37674 :     sub_var(&arg1, &arg2, &result);
                               3001                 :                : 
    1 michael@paquier.xyz      3002                 :GNC       37674 :     res = make_result_safe(&result, escontext);
                               3003                 :                : 
 9747 JanWieck@Yahoo.com       3004                 :CBC       37674 :     free_var(&result);
                               3005                 :                : 
 2366 akorotkov@postgresql     3006                 :          37674 :     return res;
                               3007                 :                : }
                               3008                 :                : 
                               3009                 :                : 
                               3010                 :                : /*
                               3011                 :                :  * numeric_mul() -
                               3012                 :                :  *
                               3013                 :                :  *  Calculate the product of two numerics
                               3014                 :                :  */
                               3015                 :                : Datum
 9170 tgl@sss.pgh.pa.us        3016                 :         244855 : numeric_mul(PG_FUNCTION_ARGS)
                               3017                 :                : {
                               3018                 :         244855 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3019                 :         244855 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3020                 :                :     Numeric     res;
                               3021                 :                : 
    1 michael@paquier.xyz      3022                 :GNC      244855 :     res = numeric_mul_safe(num1, num2, NULL);
                               3023                 :                : 
 2366 akorotkov@postgresql     3024                 :CBC      244855 :     PG_RETURN_NUMERIC(res);
                               3025                 :                : }
                               3026                 :                : 
                               3027                 :                : 
                               3028                 :                : /*
                               3029                 :                :  * numeric_mul_safe() -
                               3030                 :                :  *
                               3031                 :                :  *  Internal version of numeric_mul() with support for soft error reporting.
                               3032                 :                :  */
                               3033                 :                : Numeric
    1 michael@paquier.xyz      3034                 :GNC      244873 : numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
                               3035                 :                : {
                               3036                 :                :     NumericVar  arg1;
                               3037                 :                :     NumericVar  arg2;
                               3038                 :                :     NumericVar  result;
                               3039                 :                :     Numeric     res;
                               3040                 :                : 
                               3041                 :                :     /*
                               3042                 :                :      * Handle NaN and infinities
                               3043                 :                :      */
 1872 tgl@sss.pgh.pa.us        3044   [ +  +  +  + ]:CBC      244873 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3045                 :                :     {
                               3046   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3047                 :             39 :             return make_result(&const_nan);
                               3048         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               3049                 :                :         {
                               3050   [ +  +  +  - ]:             18 :             switch (numeric_sign_internal(num2))
                               3051                 :                :             {
                               3052                 :              3 :                 case 0:
                               3053                 :              3 :                     return make_result(&const_nan); /* Inf * 0 */
                               3054                 :              9 :                 case 1:
                               3055                 :              9 :                     return make_result(&const_pinf);
                               3056                 :              6 :                 case -1:
                               3057                 :              6 :                     return make_result(&const_ninf);
                               3058                 :                :             }
 1872 tgl@sss.pgh.pa.us        3059                 :UBC           0 :             Assert(false);
                               3060                 :                :         }
 1872 tgl@sss.pgh.pa.us        3061         [ +  + ]:CBC          42 :         if (NUMERIC_IS_NINF(num1))
                               3062                 :                :         {
                               3063   [ +  +  +  - ]:             18 :             switch (numeric_sign_internal(num2))
                               3064                 :                :             {
                               3065                 :              3 :                 case 0:
                               3066                 :              3 :                     return make_result(&const_nan); /* -Inf * 0 */
                               3067                 :              9 :                 case 1:
                               3068                 :              9 :                     return make_result(&const_ninf);
                               3069                 :              6 :                 case -1:
                               3070                 :              6 :                     return make_result(&const_pinf);
                               3071                 :                :             }
 1872 tgl@sss.pgh.pa.us        3072                 :UBC           0 :             Assert(false);
                               3073                 :                :         }
                               3074                 :                :         /* by here, num1 must be finite, so num2 is not */
 1872 tgl@sss.pgh.pa.us        3075         [ +  + ]:CBC          24 :         if (NUMERIC_IS_PINF(num2))
                               3076                 :                :         {
                               3077   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num1))
                               3078                 :                :             {
                               3079                 :              3 :                 case 0:
                               3080                 :              3 :                     return make_result(&const_nan); /* 0 * Inf */
                               3081                 :              6 :                 case 1:
                               3082                 :              6 :                     return make_result(&const_pinf);
                               3083                 :              3 :                 case -1:
                               3084                 :              3 :                     return make_result(&const_ninf);
                               3085                 :                :             }
 1872 tgl@sss.pgh.pa.us        3086                 :UBC           0 :             Assert(false);
                               3087                 :                :         }
 1872 tgl@sss.pgh.pa.us        3088         [ -  + ]:CBC          12 :         Assert(NUMERIC_IS_NINF(num2));
                               3089   [ +  +  +  - ]:             12 :         switch (numeric_sign_internal(num1))
                               3090                 :                :         {
                               3091                 :              3 :             case 0:
                               3092                 :              3 :                 return make_result(&const_nan); /* 0 * -Inf */
                               3093                 :              6 :             case 1:
                               3094                 :              6 :                 return make_result(&const_ninf);
                               3095                 :              3 :             case -1:
                               3096                 :              3 :                 return make_result(&const_pinf);
                               3097                 :                :         }
 1872 tgl@sss.pgh.pa.us        3098                 :UBC           0 :         Assert(false);
                               3099                 :                :     }
                               3100                 :                : 
                               3101                 :                :     /*
                               3102                 :                :      * Unpack the values, let mul_var() compute the result and return it.
                               3103                 :                :      * Unlike add_var() and sub_var(), mul_var() will round its result. In the
                               3104                 :                :      * case of numeric_mul(), which is invoked for the * operator on numerics,
                               3105                 :                :      * we request exact representation for the product (rscale = sum(dscale of
                               3106                 :                :      * arg1, dscale of arg2)).  If the exact result has more digits after the
                               3107                 :                :      * decimal point than can be stored in a numeric, we round it.  Rounding
                               3108                 :                :      * after computing the exact result ensures that the final result is
                               3109                 :                :      * correctly rounded (rounding in mul_var() using a truncated product
                               3110                 :                :      * would not guarantee this).
                               3111                 :                :      */
 4672 heikki.linnakangas@i     3112                 :CBC      244774 :     init_var_from_num(num1, &arg1);
                               3113                 :         244774 :     init_var_from_num(num2, &arg2);
                               3114                 :                : 
                               3115                 :         244774 :     init_var(&result);
 8205 tgl@sss.pgh.pa.us        3116                 :         244774 :     mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
                               3117                 :                : 
 1519 dean.a.rasheed@gmail     3118         [ +  + ]:         244774 :     if (result.dscale > NUMERIC_DSCALE_MAX)
                               3119                 :              3 :         round_var(&result, NUMERIC_DSCALE_MAX);
                               3120                 :                : 
    1 michael@paquier.xyz      3121                 :GNC      244774 :     res = make_result_safe(&result, escontext);
                               3122                 :                : 
 9747 JanWieck@Yahoo.com       3123                 :CBC      244774 :     free_var(&result);
                               3124                 :                : 
 2366 akorotkov@postgresql     3125                 :         244774 :     return res;
                               3126                 :                : }
                               3127                 :                : 
                               3128                 :                : 
                               3129                 :                : /*
                               3130                 :                :  * numeric_div() -
                               3131                 :                :  *
                               3132                 :                :  *  Divide one numeric into another
                               3133                 :                :  */
                               3134                 :                : Datum
 9170 tgl@sss.pgh.pa.us        3135                 :          74129 : numeric_div(PG_FUNCTION_ARGS)
                               3136                 :                : {
                               3137                 :          74129 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3138                 :          74129 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3139                 :                :     Numeric     res;
                               3140                 :                : 
    1 michael@paquier.xyz      3141                 :GNC       74129 :     res = numeric_div_safe(num1, num2, NULL);
                               3142                 :                : 
 2366 akorotkov@postgresql     3143                 :CBC       74113 :     PG_RETURN_NUMERIC(res);
                               3144                 :                : }
                               3145                 :                : 
                               3146                 :                : 
                               3147                 :                : /*
                               3148                 :                :  * numeric_div_safe() -
                               3149                 :                :  *
                               3150                 :                :  *  Internal version of numeric_div() with support for soft error reporting.
                               3151                 :                :  */
                               3152                 :                : Numeric
    1 michael@paquier.xyz      3153                 :GNC       74549 : numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
                               3154                 :                : {
                               3155                 :                :     NumericVar  arg1;
                               3156                 :                :     NumericVar  arg2;
                               3157                 :                :     NumericVar  result;
                               3158                 :                :     Numeric     res;
                               3159                 :                :     int         rscale;
                               3160                 :                : 
                               3161                 :                :     /*
                               3162                 :                :      * Handle NaN and infinities
                               3163                 :                :      */
 1872 tgl@sss.pgh.pa.us        3164   [ +  +  +  + ]:CBC       74549 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3165                 :                :     {
                               3166   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3167                 :             39 :             return make_result(&const_nan);
                               3168         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               3169                 :                :         {
                               3170         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3171                 :              6 :                 return make_result(&const_nan); /* Inf / [-]Inf */
                               3172   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3173                 :                :             {
                               3174                 :              3 :                 case 0:
    1 michael@paquier.xyz      3175                 :GNC           3 :                     goto division_by_zero;
 1872 tgl@sss.pgh.pa.us        3176                 :CBC           6 :                 case 1:
                               3177                 :              6 :                     return make_result(&const_pinf);
                               3178                 :              3 :                 case -1:
                               3179                 :              3 :                     return make_result(&const_ninf);
                               3180                 :                :             }
 1872 tgl@sss.pgh.pa.us        3181                 :UBC           0 :             Assert(false);
                               3182                 :                :         }
 1872 tgl@sss.pgh.pa.us        3183         [ +  + ]:CBC          42 :         if (NUMERIC_IS_NINF(num1))
                               3184                 :                :         {
                               3185         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3186                 :              6 :                 return make_result(&const_nan); /* -Inf / [-]Inf */
                               3187   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3188                 :                :             {
                               3189                 :              3 :                 case 0:
    1 michael@paquier.xyz      3190                 :GNC           3 :                     goto division_by_zero;
 1872 tgl@sss.pgh.pa.us        3191                 :CBC           6 :                 case 1:
                               3192                 :              6 :                     return make_result(&const_ninf);
                               3193                 :              3 :                 case -1:
                               3194                 :              3 :                     return make_result(&const_pinf);
                               3195                 :                :             }
 1872 tgl@sss.pgh.pa.us        3196                 :UBC           0 :             Assert(false);
                               3197                 :                :         }
                               3198                 :                :         /* by here, num1 must be finite, so num2 is not */
                               3199                 :                : 
                               3200                 :                :         /*
                               3201                 :                :          * POSIX would have us return zero or minus zero if num1 is zero, and
                               3202                 :                :          * otherwise throw an underflow error.  But the numeric type doesn't
                               3203                 :                :          * really do underflow, so let's just return zero.
                               3204                 :                :          */
 1872 tgl@sss.pgh.pa.us        3205                 :CBC          24 :         return make_result(&const_zero);
                               3206                 :                :     }
                               3207                 :                : 
                               3208                 :                :     /*
                               3209                 :                :      * Unpack the arguments
                               3210                 :                :      */
 4672 heikki.linnakangas@i     3211                 :          74450 :     init_var_from_num(num1, &arg1);
                               3212                 :          74450 :     init_var_from_num(num2, &arg2);
                               3213                 :                : 
                               3214                 :          74450 :     init_var(&result);
                               3215                 :                : 
                               3216                 :                :     /*
                               3217                 :                :      * Select scale for division result
                               3218                 :                :      */
 8205 tgl@sss.pgh.pa.us        3219                 :          74450 :     rscale = select_div_scale(&arg1, &arg2);
                               3220                 :                : 
                               3221                 :                :     /* Check for division by zero */
    1 michael@paquier.xyz      3222   [ +  +  -  + ]:GNC       74450 :     if (arg2.ndigits == 0 || arg2.digits[0] == 0)
                               3223                 :             25 :         goto division_by_zero;
                               3224                 :                : 
                               3225                 :                :     /*
                               3226                 :                :      * Do the divide and return the result
                               3227                 :                :      */
  337 dean.a.rasheed@gmail     3228                 :CBC       74425 :     div_var(&arg1, &arg2, &result, rscale, true, true);
                               3229                 :                : 
    1 michael@paquier.xyz      3230                 :GNC       74425 :     res = make_result_safe(&result, escontext);
                               3231                 :                : 
 9747 JanWieck@Yahoo.com       3232                 :CBC       74425 :     free_var(&result);
                               3233                 :                : 
 2366 akorotkov@postgresql     3234                 :          74425 :     return res;
                               3235                 :                : 
    1 michael@paquier.xyz      3236                 :GNC          31 : division_by_zero:
                               3237         [ +  + ]:             31 :     ereturn(escontext, NULL,
                               3238                 :                :             errcode(ERRCODE_DIVISION_BY_ZERO),
                               3239                 :                :             errmsg("division by zero"));
                               3240                 :                : }
                               3241                 :                : 
                               3242                 :                : 
                               3243                 :                : /*
                               3244                 :                :  * numeric_div_trunc() -
                               3245                 :                :  *
                               3246                 :                :  *  Divide one numeric into another, truncating the result to an integer
                               3247                 :                :  */
                               3248                 :                : Datum
 6364 tgl@sss.pgh.pa.us        3249                 :CBC         609 : numeric_div_trunc(PG_FUNCTION_ARGS)
                               3250                 :                : {
                               3251                 :            609 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3252                 :            609 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3253                 :                :     NumericVar  arg1;
                               3254                 :                :     NumericVar  arg2;
                               3255                 :                :     NumericVar  result;
                               3256                 :                :     Numeric     res;
                               3257                 :                : 
                               3258                 :                :     /*
                               3259                 :                :      * Handle NaN and infinities
                               3260                 :                :      */
 1872                          3261   [ +  +  +  + ]:            609 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3262                 :                :     {
                               3263   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3264                 :             39 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3265         [ +  + ]:             60 :         if (NUMERIC_IS_PINF(num1))
                               3266                 :                :         {
                               3267         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3268                 :              6 :                 PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
                               3269   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3270                 :                :             {
                               3271                 :              3 :                 case 0:
                               3272         [ +  - ]:              3 :                     ereport(ERROR,
                               3273                 :                :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3274                 :                :                              errmsg("division by zero")));
                               3275                 :                :                     break;
                               3276                 :              6 :                 case 1:
                               3277                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_pinf));
                               3278                 :              3 :                 case -1:
                               3279                 :              3 :                     PG_RETURN_NUMERIC(make_result(&const_ninf));
                               3280                 :                :             }
 1872 tgl@sss.pgh.pa.us        3281                 :UBC           0 :             Assert(false);
                               3282                 :                :         }
 1872 tgl@sss.pgh.pa.us        3283         [ +  + ]:CBC          42 :         if (NUMERIC_IS_NINF(num1))
                               3284                 :                :         {
                               3285         [ +  + ]:             18 :             if (NUMERIC_IS_SPECIAL(num2))
                               3286                 :              6 :                 PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
                               3287   [ +  +  +  - ]:             12 :             switch (numeric_sign_internal(num2))
                               3288                 :                :             {
                               3289                 :              3 :                 case 0:
                               3290         [ +  - ]:              3 :                     ereport(ERROR,
                               3291                 :                :                             (errcode(ERRCODE_DIVISION_BY_ZERO),
                               3292                 :                :                              errmsg("division by zero")));
                               3293                 :                :                     break;
                               3294                 :              6 :                 case 1:
                               3295                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_ninf));
                               3296                 :              3 :                 case -1:
                               3297                 :              3 :                     PG_RETURN_NUMERIC(make_result(&const_pinf));
                               3298                 :                :             }
 1872 tgl@sss.pgh.pa.us        3299                 :UBC           0 :             Assert(false);
                               3300                 :                :         }
                               3301                 :                :         /* by here, num1 must be finite, so num2 is not */
                               3302                 :                : 
                               3303                 :                :         /*
                               3304                 :                :          * POSIX would have us return zero or minus zero if num1 is zero, and
                               3305                 :                :          * otherwise throw an underflow error.  But the numeric type doesn't
                               3306                 :                :          * really do underflow, so let's just return zero.
                               3307                 :                :          */
 1872 tgl@sss.pgh.pa.us        3308                 :CBC          24 :         PG_RETURN_NUMERIC(make_result(&const_zero));
                               3309                 :                :     }
                               3310                 :                : 
                               3311                 :                :     /*
                               3312                 :                :      * Unpack the arguments
                               3313                 :                :      */
 4672 heikki.linnakangas@i     3314                 :            510 :     init_var_from_num(num1, &arg1);
                               3315                 :            510 :     init_var_from_num(num2, &arg2);
                               3316                 :                : 
                               3317                 :            510 :     init_var(&result);
                               3318                 :                : 
                               3319                 :                :     /*
                               3320                 :                :      * Do the divide and return the result
                               3321                 :                :      */
  337 dean.a.rasheed@gmail     3322                 :            510 :     div_var(&arg1, &arg2, &result, 0, false, true);
                               3323                 :                : 
 6364 tgl@sss.pgh.pa.us        3324                 :            507 :     res = make_result(&result);
                               3325                 :                : 
                               3326                 :            507 :     free_var(&result);
                               3327                 :                : 
                               3328                 :            507 :     PG_RETURN_NUMERIC(res);
                               3329                 :                : }
                               3330                 :                : 
                               3331                 :                : 
                               3332                 :                : /*
                               3333                 :                :  * numeric_mod() -
                               3334                 :                :  *
                               3335                 :                :  *  Calculate the modulo of two numerics
                               3336                 :                :  */
                               3337                 :                : Datum
 9170                          3338                 :         206649 : numeric_mod(PG_FUNCTION_ARGS)
                               3339                 :                : {
                               3340                 :         206649 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3341                 :         206649 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3342                 :                :     Numeric     res;
                               3343                 :                : 
    1 michael@paquier.xyz      3344                 :GNC      206649 :     res = numeric_mod_safe(num1, num2, NULL);
                               3345                 :                : 
 2366 akorotkov@postgresql     3346                 :CBC      206640 :     PG_RETURN_NUMERIC(res);
                               3347                 :                : }
                               3348                 :                : 
                               3349                 :                : 
                               3350                 :                : /*
                               3351                 :                :  * numeric_mod_safe() -
                               3352                 :                :  *
                               3353                 :                :  *  Internal version of numeric_mod() with support for soft error reporting.
                               3354                 :                :  */
                               3355                 :                : Numeric
    1 michael@paquier.xyz      3356                 :GNC      206655 : numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
                               3357                 :                : {
                               3358                 :                :     Numeric     res;
                               3359                 :                :     NumericVar  arg1;
                               3360                 :                :     NumericVar  arg2;
                               3361                 :                :     NumericVar  result;
                               3362                 :                : 
                               3363                 :                :     /*
                               3364                 :                :      * Handle NaN and infinities.  We follow POSIX fmod() on this, except that
                               3365                 :                :      * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
                               3366                 :                :      * returning NaN.  We choose to throw error only for y-is-zero.
                               3367                 :                :      */
 1872 tgl@sss.pgh.pa.us        3368   [ +  +  +  + ]:CBC      206655 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3369                 :                :     {
                               3370   [ +  +  +  + ]:             99 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3371                 :             39 :             return make_result(&const_nan);
                               3372         [ +  + ]:             60 :         if (NUMERIC_IS_INF(num1))
                               3373                 :                :         {
                               3374         [ +  + ]:             36 :             if (numeric_sign_internal(num2) == 0)
    1 michael@paquier.xyz      3375                 :GNC           6 :                 goto division_by_zero;
                               3376                 :                : 
                               3377                 :                :             /* Inf % any nonzero = NaN */
 1872 tgl@sss.pgh.pa.us        3378                 :CBC          30 :             return make_result(&const_nan);
                               3379                 :                :         }
                               3380                 :                :         /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
                               3381                 :             24 :         return duplicate_numeric(num1);
                               3382                 :                :     }
                               3383                 :                : 
 4672 heikki.linnakangas@i     3384                 :         206556 :     init_var_from_num(num1, &arg1);
                               3385                 :         206556 :     init_var_from_num(num2, &arg2);
                               3386                 :                : 
                               3387                 :         206556 :     init_var(&result);
                               3388                 :                : 
                               3389                 :                :     /* Check for division by zero */
    1 michael@paquier.xyz      3390   [ +  +  -  + ]:GNC      206556 :     if (arg2.ndigits == 0 || arg2.digits[0] == 0)
                               3391                 :              6 :         goto division_by_zero;
                               3392                 :                : 
 9747 JanWieck@Yahoo.com       3393                 :CBC      206550 :     mod_var(&arg1, &arg2, &result);
                               3394                 :                : 
    1 michael@paquier.xyz      3395                 :GNC      206550 :     res = make_result_safe(&result, escontext);
                               3396                 :                : 
 9747 JanWieck@Yahoo.com       3397                 :CBC      206550 :     free_var(&result);
                               3398                 :                : 
 2366 akorotkov@postgresql     3399                 :         206550 :     return res;
                               3400                 :                : 
    1 michael@paquier.xyz      3401                 :GNC          12 : division_by_zero:
                               3402         [ +  - ]:             12 :     ereturn(escontext, NULL,
                               3403                 :                :             errcode(ERRCODE_DIVISION_BY_ZERO),
                               3404                 :                :             errmsg("division by zero"));
                               3405                 :                : }
                               3406                 :                : 
                               3407                 :                : 
                               3408                 :                : /*
                               3409                 :                :  * numeric_inc() -
                               3410                 :                :  *
                               3411                 :                :  *  Increment a number by one
                               3412                 :                :  */
                               3413                 :                : Datum
 9170 tgl@sss.pgh.pa.us        3414                 :CBC          24 : numeric_inc(PG_FUNCTION_ARGS)
                               3415                 :                : {
                               3416                 :             24 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3417                 :                :     NumericVar  arg;
                               3418                 :                :     Numeric     res;
                               3419                 :                : 
                               3420                 :                :     /*
                               3421                 :                :      * Handle NaN and infinities
                               3422                 :                :      */
 1872                          3423         [ +  + ]:             24 :     if (NUMERIC_IS_SPECIAL(num))
                               3424                 :              9 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3425                 :                : 
                               3426                 :                :     /*
                               3427                 :                :      * Compute the result and return it
                               3428                 :                :      */
 4672 heikki.linnakangas@i     3429                 :             15 :     init_var_from_num(num, &arg);
                               3430                 :                : 
 9747 JanWieck@Yahoo.com       3431                 :             15 :     add_var(&arg, &const_one, &arg);
                               3432                 :                : 
                               3433                 :             15 :     res = make_result(&arg);
                               3434                 :                : 
                               3435                 :             15 :     free_var(&arg);
                               3436                 :                : 
 9170 tgl@sss.pgh.pa.us        3437                 :             15 :     PG_RETURN_NUMERIC(res);
                               3438                 :                : }
                               3439                 :                : 
                               3440                 :                : 
                               3441                 :                : /*
                               3442                 :                :  * numeric_smaller() -
                               3443                 :                :  *
                               3444                 :                :  *  Return the smaller of two numbers
                               3445                 :                :  */
                               3446                 :                : Datum
                               3447                 :            399 : numeric_smaller(PG_FUNCTION_ARGS)
                               3448                 :                : {
                               3449                 :            399 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3450                 :            399 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3451                 :                : 
                               3452                 :                :     /*
                               3453                 :                :      * Use cmp_numerics so that this will agree with the comparison operators,
                               3454                 :                :      * particularly as regards comparisons involving NaN.
                               3455                 :                :      */
 8074                          3456         [ +  + ]:            399 :     if (cmp_numerics(num1, num2) < 0)
                               3457                 :            321 :         PG_RETURN_NUMERIC(num1);
                               3458                 :                :     else
                               3459                 :             78 :         PG_RETURN_NUMERIC(num2);
                               3460                 :                : }
                               3461                 :                : 
                               3462                 :                : 
                               3463                 :                : /*
                               3464                 :                :  * numeric_larger() -
                               3465                 :                :  *
                               3466                 :                :  *  Return the larger of two numbers
                               3467                 :                :  */
                               3468                 :                : Datum
 9170                          3469                 :           9315 : numeric_larger(PG_FUNCTION_ARGS)
                               3470                 :                : {
                               3471                 :           9315 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3472                 :           9315 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3473                 :                : 
                               3474                 :                :     /*
                               3475                 :                :      * Use cmp_numerics so that this will agree with the comparison operators,
                               3476                 :                :      * particularly as regards comparisons involving NaN.
                               3477                 :                :      */
 8074                          3478         [ +  + ]:           9315 :     if (cmp_numerics(num1, num2) > 0)
                               3479                 :           9000 :         PG_RETURN_NUMERIC(num1);
                               3480                 :                :     else
                               3481                 :            315 :         PG_RETURN_NUMERIC(num2);
                               3482                 :                : }
                               3483                 :                : 
                               3484                 :                : 
                               3485                 :                : /* ----------------------------------------------------------------------
                               3486                 :                :  *
                               3487                 :                :  * Advanced math functions
                               3488                 :                :  *
                               3489                 :                :  * ----------------------------------------------------------------------
                               3490                 :                :  */
                               3491                 :                : 
                               3492                 :                : /*
                               3493                 :                :  * numeric_gcd() -
                               3494                 :                :  *
                               3495                 :                :  *  Calculate the greatest common divisor of two numerics
                               3496                 :                :  */
                               3497                 :                : Datum
 2051 dean.a.rasheed@gmail     3498                 :            108 : numeric_gcd(PG_FUNCTION_ARGS)
                               3499                 :                : {
                               3500                 :            108 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3501                 :            108 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3502                 :                :     NumericVar  arg1;
                               3503                 :                :     NumericVar  arg2;
                               3504                 :                :     NumericVar  result;
                               3505                 :                :     Numeric     res;
                               3506                 :                : 
                               3507                 :                :     /*
                               3508                 :                :      * Handle NaN and infinities: we consider the result to be NaN in all such
                               3509                 :                :      * cases.
                               3510                 :                :      */
 1872 tgl@sss.pgh.pa.us        3511   [ +  +  +  + ]:            108 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 2051 dean.a.rasheed@gmail     3512                 :             48 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               3513                 :                : 
                               3514                 :                :     /*
                               3515                 :                :      * Unpack the arguments
                               3516                 :                :      */
                               3517                 :             60 :     init_var_from_num(num1, &arg1);
                               3518                 :             60 :     init_var_from_num(num2, &arg2);
                               3519                 :                : 
                               3520                 :             60 :     init_var(&result);
                               3521                 :                : 
                               3522                 :                :     /*
                               3523                 :                :      * Find the GCD and return the result
                               3524                 :                :      */
                               3525                 :             60 :     gcd_var(&arg1, &arg2, &result);
                               3526                 :                : 
                               3527                 :             60 :     res = make_result(&result);
                               3528                 :                : 
                               3529                 :             60 :     free_var(&result);
                               3530                 :                : 
                               3531                 :             60 :     PG_RETURN_NUMERIC(res);
                               3532                 :                : }
                               3533                 :                : 
                               3534                 :                : 
                               3535                 :                : /*
                               3536                 :                :  * numeric_lcm() -
                               3537                 :                :  *
                               3538                 :                :  *  Calculate the least common multiple of two numerics
                               3539                 :                :  */
                               3540                 :                : Datum
                               3541                 :            123 : numeric_lcm(PG_FUNCTION_ARGS)
                               3542                 :                : {
                               3543                 :            123 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3544                 :            123 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3545                 :                :     NumericVar  arg1;
                               3546                 :                :     NumericVar  arg2;
                               3547                 :                :     NumericVar  result;
                               3548                 :                :     Numeric     res;
                               3549                 :                : 
                               3550                 :                :     /*
                               3551                 :                :      * Handle NaN and infinities: we consider the result to be NaN in all such
                               3552                 :                :      * cases.
                               3553                 :                :      */
 1872 tgl@sss.pgh.pa.us        3554   [ +  +  +  + ]:            123 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 2051 dean.a.rasheed@gmail     3555                 :             48 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               3556                 :                : 
                               3557                 :                :     /*
                               3558                 :                :      * Unpack the arguments
                               3559                 :                :      */
                               3560                 :             75 :     init_var_from_num(num1, &arg1);
                               3561                 :             75 :     init_var_from_num(num2, &arg2);
                               3562                 :                : 
                               3563                 :             75 :     init_var(&result);
                               3564                 :                : 
                               3565                 :                :     /*
                               3566                 :                :      * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
                               3567                 :                :      * zero if either input is zero.
                               3568                 :                :      *
                               3569                 :                :      * Note that the division is guaranteed to be exact, returning an integer
                               3570                 :                :      * result, so the LCM is an integral multiple of both x and y.  A display
                               3571                 :                :      * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
                               3572                 :                :      * but as with other numeric functions, we choose to return a result whose
                               3573                 :                :      * display scale is no smaller than either input.
                               3574                 :                :      */
                               3575   [ +  +  +  + ]:             75 :     if (arg1.ndigits == 0 || arg2.ndigits == 0)
                               3576                 :             24 :         set_var_from_var(&const_zero, &result);
                               3577                 :                :     else
                               3578                 :                :     {
                               3579                 :             51 :         gcd_var(&arg1, &arg2, &result);
  337                          3580                 :             51 :         div_var(&arg1, &result, &result, 0, false, true);
 2051                          3581                 :             51 :         mul_var(&arg2, &result, &result, arg2.dscale);
                               3582                 :             51 :         result.sign = NUMERIC_POS;
                               3583                 :                :     }
                               3584                 :                : 
                               3585                 :             75 :     result.dscale = Max(arg1.dscale, arg2.dscale);
                               3586                 :                : 
                               3587                 :             75 :     res = make_result(&result);
                               3588                 :                : 
                               3589                 :             72 :     free_var(&result);
                               3590                 :                : 
                               3591                 :             72 :     PG_RETURN_NUMERIC(res);
                               3592                 :                : }
                               3593                 :                : 
                               3594                 :                : 
                               3595                 :                : /*
                               3596                 :                :  * numeric_fac()
                               3597                 :                :  *
                               3598                 :                :  * Compute factorial
                               3599                 :                :  */
                               3600                 :                : Datum
 7950 bruce@momjian.us         3601                 :             21 : numeric_fac(PG_FUNCTION_ARGS)
                               3602                 :                : {
                               3603                 :             21 :     int64       num = PG_GETARG_INT64(0);
                               3604                 :                :     Numeric     res;
                               3605                 :                :     NumericVar  fact;
                               3606                 :                :     NumericVar  result;
                               3607                 :                : 
 1906 peter@eisentraut.org     3608         [ +  + ]:             21 :     if (num < 0)
                               3609         [ +  - ]:              3 :         ereport(ERROR,
                               3610                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               3611                 :                :                  errmsg("factorial of a negative number is undefined")));
 7949 tgl@sss.pgh.pa.us        3612         [ +  + ]:             18 :     if (num <= 1)
                               3613                 :                :     {
 7950 bruce@momjian.us         3614                 :              3 :         res = make_result(&const_one);
                               3615                 :              3 :         PG_RETURN_NUMERIC(res);
                               3616                 :                :     }
                               3617                 :                :     /* Fail immediately if the result would overflow */
 6664 tgl@sss.pgh.pa.us        3618         [ +  + ]:             15 :     if (num > 32177)
                               3619         [ +  - ]:              3 :         ereport(ERROR,
                               3620                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               3621                 :                :                  errmsg("value overflows numeric format")));
                               3622                 :                : 
 7950 bruce@momjian.us         3623                 :             12 :     init_var(&fact);
                               3624                 :             12 :     init_var(&result);
                               3625                 :                : 
 3823 andres@anarazel.de       3626                 :             12 :     int64_to_numericvar(num, &result);
                               3627                 :                : 
 7949 tgl@sss.pgh.pa.us        3628         [ +  + ]:            147 :     for (num = num - 1; num > 1; num--)
                               3629                 :                :     {
                               3630                 :                :         /* this loop can take awhile, so allow it to be interrupted */
 6664                          3631         [ -  + ]:            135 :         CHECK_FOR_INTERRUPTS();
                               3632                 :                : 
 3823 andres@anarazel.de       3633                 :            135 :         int64_to_numericvar(num, &fact);
                               3634                 :                : 
 7949 tgl@sss.pgh.pa.us        3635                 :            135 :         mul_var(&result, &fact, &result, 0);
                               3636                 :                :     }
                               3637                 :                : 
                               3638                 :             12 :     res = make_result(&result);
                               3639                 :                : 
 7950 bruce@momjian.us         3640                 :             12 :     free_var(&fact);
                               3641                 :             12 :     free_var(&result);
                               3642                 :                : 
                               3643                 :             12 :     PG_RETURN_NUMERIC(res);
                               3644                 :                : }
                               3645                 :                : 
                               3646                 :                : 
                               3647                 :                : /*
                               3648                 :                :  * numeric_sqrt() -
                               3649                 :                :  *
                               3650                 :                :  *  Compute the square root of a numeric.
                               3651                 :                :  */
                               3652                 :                : Datum
 9170 tgl@sss.pgh.pa.us        3653                 :             75 : numeric_sqrt(PG_FUNCTION_ARGS)
                               3654                 :                : {
                               3655                 :             75 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3656                 :                :     Numeric     res;
                               3657                 :                :     NumericVar  arg;
                               3658                 :                :     NumericVar  result;
                               3659                 :                :     int         sweight;
                               3660                 :                :     int         rscale;
                               3661                 :                : 
                               3662                 :                :     /*
                               3663                 :                :      * Handle NaN and infinities
                               3664                 :                :      */
 1872                          3665         [ +  + ]:             75 :     if (NUMERIC_IS_SPECIAL(num))
                               3666                 :                :     {
                               3667                 :                :         /* error should match that in sqrt_var() */
                               3668         [ +  + ]:              9 :         if (NUMERIC_IS_NINF(num))
                               3669         [ +  - ]:              3 :             ereport(ERROR,
                               3670                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               3671                 :                :                      errmsg("cannot take square root of a negative number")));
                               3672                 :                :         /* For NAN or PINF, just duplicate the input */
                               3673                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3674                 :                :     }
                               3675                 :                : 
                               3676                 :                :     /*
                               3677                 :                :      * Unpack the argument and determine the result scale.  We choose a scale
                               3678                 :                :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
                               3679                 :                :      * case not less than the input's dscale.
                               3680                 :                :      */
 4672 heikki.linnakangas@i     3681                 :             66 :     init_var_from_num(num, &arg);
                               3682                 :                : 
                               3683                 :             66 :     init_var(&result);
                               3684                 :                : 
                               3685                 :                :     /*
                               3686                 :                :      * Assume the input was normalized, so arg.weight is accurate.  The result
                               3687                 :                :      * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
                               3688                 :                :      * digits before the decimal point.  When DEC_DIGITS is even, we can save
                               3689                 :                :      * a few cycles, since the division is exact and there is no need to round
                               3690                 :                :      * towards negative infinity.
                               3691                 :                :      */
                               3692                 :                : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
  947 dean.a.rasheed@gmail     3693                 :             66 :     sweight = arg.weight * DEC_DIGITS / 2 + 1;
                               3694                 :                : #else
                               3695                 :                :     if (arg.weight >= 0)
                               3696                 :                :         sweight = arg.weight * DEC_DIGITS / 2 + 1;
                               3697                 :                :     else
                               3698                 :                :         sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
                               3699                 :                : #endif
                               3700                 :                : 
 8205 tgl@sss.pgh.pa.us        3701                 :             66 :     rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
                               3702                 :             66 :     rscale = Max(rscale, arg.dscale);
                               3703                 :             66 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               3704                 :             66 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               3705                 :                : 
                               3706                 :                :     /*
                               3707                 :                :      * Let sqrt_var() do the calculation and return the result.
                               3708                 :                :      */
                               3709                 :             66 :     sqrt_var(&arg, &result, rscale);
                               3710                 :                : 
 9747 JanWieck@Yahoo.com       3711                 :             63 :     res = make_result(&result);
                               3712                 :                : 
                               3713                 :             63 :     free_var(&result);
                               3714                 :                : 
 9170 tgl@sss.pgh.pa.us        3715                 :             63 :     PG_RETURN_NUMERIC(res);
                               3716                 :                : }
                               3717                 :                : 
                               3718                 :                : 
                               3719                 :                : /*
                               3720                 :                :  * numeric_exp() -
                               3721                 :                :  *
                               3722                 :                :  *  Raise e to the power of x
                               3723                 :                :  */
                               3724                 :                : Datum
                               3725                 :             39 : numeric_exp(PG_FUNCTION_ARGS)
                               3726                 :                : {
                               3727                 :             39 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3728                 :                :     Numeric     res;
                               3729                 :                :     NumericVar  arg;
                               3730                 :                :     NumericVar  result;
                               3731                 :                :     int         rscale;
                               3732                 :                :     double      val;
                               3733                 :                : 
                               3734                 :                :     /*
                               3735                 :                :      * Handle NaN and infinities
                               3736                 :                :      */
 1872                          3737         [ +  + ]:             39 :     if (NUMERIC_IS_SPECIAL(num))
                               3738                 :                :     {
                               3739                 :                :         /* Per POSIX, exp(-Inf) is zero */
                               3740         [ +  + ]:              9 :         if (NUMERIC_IS_NINF(num))
                               3741                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               3742                 :                :         /* For NAN or PINF, just duplicate the input */
                               3743                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3744                 :                :     }
                               3745                 :                : 
                               3746                 :                :     /*
                               3747                 :                :      * Unpack the argument and determine the result scale.  We choose a scale
                               3748                 :                :      * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
                               3749                 :                :      * case not less than the input's dscale.
                               3750                 :                :      */
 4672 heikki.linnakangas@i     3751                 :             30 :     init_var_from_num(num, &arg);
                               3752                 :                : 
                               3753                 :             30 :     init_var(&result);
                               3754                 :                : 
                               3755                 :                :     /* convert input to float8, ignoring overflow */
 8205 tgl@sss.pgh.pa.us        3756                 :             30 :     val = numericvar_to_double_no_overflow(&arg);
                               3757                 :                : 
                               3758                 :                :     /*
                               3759                 :                :      * log10(result) = num * log10(e), so this is approximately the decimal
                               3760                 :                :      * weight of the result:
                               3761                 :                :      */
 8375                          3762                 :             30 :     val *= 0.434294481903252;
                               3763                 :                : 
                               3764                 :                :     /* limit to something that won't cause integer overflow */
                               3765         [ +  + ]:             30 :     val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
                               3766         [ +  - ]:             30 :     val = Min(val, NUMERIC_MAX_RESULT_SCALE);
                               3767                 :                : 
 8205                          3768                 :             30 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
                               3769                 :             30 :     rscale = Max(rscale, arg.dscale);
                               3770                 :             30 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               3771                 :             30 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               3772                 :                : 
                               3773                 :                :     /*
                               3774                 :                :      * Let exp_var() do the calculation and return the result.
                               3775                 :                :      */
                               3776                 :             30 :     exp_var(&arg, &result, rscale);
                               3777                 :                : 
 9747 JanWieck@Yahoo.com       3778                 :             30 :     res = make_result(&result);
                               3779                 :                : 
                               3780                 :             30 :     free_var(&result);
                               3781                 :                : 
 9170 tgl@sss.pgh.pa.us        3782                 :             30 :     PG_RETURN_NUMERIC(res);
                               3783                 :                : }
                               3784                 :                : 
                               3785                 :                : 
                               3786                 :                : /*
                               3787                 :                :  * numeric_ln() -
                               3788                 :                :  *
                               3789                 :                :  *  Compute the natural logarithm of x
                               3790                 :                :  */
                               3791                 :                : Datum
                               3792                 :             99 : numeric_ln(PG_FUNCTION_ARGS)
                               3793                 :                : {
                               3794                 :             99 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               3795                 :                :     Numeric     res;
                               3796                 :                :     NumericVar  arg;
                               3797                 :                :     NumericVar  result;
                               3798                 :                :     int         ln_dweight;
                               3799                 :                :     int         rscale;
                               3800                 :                : 
                               3801                 :                :     /*
                               3802                 :                :      * Handle NaN and infinities
                               3803                 :                :      */
 1872                          3804         [ +  + ]:             99 :     if (NUMERIC_IS_SPECIAL(num))
                               3805                 :                :     {
                               3806         [ +  + ]:              9 :         if (NUMERIC_IS_NINF(num))
                               3807         [ +  - ]:              3 :             ereport(ERROR,
                               3808                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                               3809                 :                :                      errmsg("cannot take logarithm of a negative number")));
                               3810                 :                :         /* For NAN or PINF, just duplicate the input */
                               3811                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               3812                 :                :     }
                               3813                 :                : 
 4672 heikki.linnakangas@i     3814                 :             90 :     init_var_from_num(num, &arg);
 9747 JanWieck@Yahoo.com       3815                 :             90 :     init_var(&result);
                               3816                 :                : 
                               3817                 :                :     /* Estimated dweight of logarithm */
 3584 tgl@sss.pgh.pa.us        3818                 :             90 :     ln_dweight = estimate_ln_dweight(&arg);
                               3819                 :                : 
                               3820                 :             90 :     rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
 8205                          3821                 :             90 :     rscale = Max(rscale, arg.dscale);
                               3822                 :             90 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               3823                 :             90 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               3824                 :                : 
                               3825                 :             90 :     ln_var(&arg, &result, rscale);
                               3826                 :                : 
 9747 JanWieck@Yahoo.com       3827                 :             78 :     res = make_result(&result);
                               3828                 :                : 
                               3829                 :             78 :     free_var(&result);
                               3830                 :                : 
 9170 tgl@sss.pgh.pa.us        3831                 :             78 :     PG_RETURN_NUMERIC(res);
                               3832                 :                : }
                               3833                 :                : 
                               3834                 :                : 
                               3835                 :                : /*
                               3836                 :                :  * numeric_log() -
                               3837                 :                :  *
                               3838                 :                :  *  Compute the logarithm of x in a given base
                               3839                 :                :  */
                               3840                 :                : Datum
                               3841                 :            171 : numeric_log(PG_FUNCTION_ARGS)
                               3842                 :                : {
                               3843                 :            171 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3844                 :            171 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3845                 :                :     Numeric     res;
                               3846                 :                :     NumericVar  arg1;
                               3847                 :                :     NumericVar  arg2;
                               3848                 :                :     NumericVar  result;
                               3849                 :                : 
                               3850                 :                :     /*
                               3851                 :                :      * Handle NaN and infinities
                               3852                 :                :      */
 1872                          3853   [ +  +  +  + ]:            171 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3854                 :                :     {
                               3855                 :                :         int         sign1,
                               3856                 :                :                     sign2;
                               3857                 :                : 
                               3858   [ +  +  +  + ]:             63 :         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
                               3859                 :             27 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3860                 :                :         /* fail on negative inputs including -Inf, as log_var would */
                               3861                 :             36 :         sign1 = numeric_sign_internal(num1);
                               3862                 :             36 :         sign2 = numeric_sign_internal(num2);
                               3863   [ +  +  +  + ]:             36 :         if (sign1 < 0 || sign2 < 0)
                               3864         [ +  - ]:             12 :             ereport(ERROR,
                               3865                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                               3866                 :                :                      errmsg("cannot take logarithm of a negative number")));
                               3867                 :                :         /* fail on zero inputs, as log_var would */
                               3868   [ +  -  +  + ]:             24 :         if (sign1 == 0 || sign2 == 0)
                               3869         [ +  - ]:              3 :             ereport(ERROR,
                               3870                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                               3871                 :                :                      errmsg("cannot take logarithm of zero")));
                               3872         [ +  + ]:             21 :         if (NUMERIC_IS_PINF(num1))
                               3873                 :                :         {
                               3874                 :                :             /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
                               3875         [ +  + ]:              9 :             if (NUMERIC_IS_PINF(num2))
                               3876                 :              3 :                 PG_RETURN_NUMERIC(make_result(&const_nan));
                               3877                 :                :             /* log(Inf, finite-positive) is zero (we don't throw underflow) */
                               3878                 :              6 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               3879                 :                :         }
                               3880         [ -  + ]:             12 :         Assert(NUMERIC_IS_PINF(num2));
                               3881                 :                :         /* log(finite-positive, Inf) is Inf */
                               3882                 :             12 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
                               3883                 :                :     }
                               3884                 :                : 
                               3885                 :                :     /*
                               3886                 :                :      * Initialize things
                               3887                 :                :      */
 4672 heikki.linnakangas@i     3888                 :            108 :     init_var_from_num(num1, &arg1);
                               3889                 :            108 :     init_var_from_num(num2, &arg2);
 9747 JanWieck@Yahoo.com       3890                 :            108 :     init_var(&result);
                               3891                 :                : 
                               3892                 :                :     /*
                               3893                 :                :      * Call log_var() to compute and return the result; note it handles scale
                               3894                 :                :      * selection itself.
                               3895                 :                :      */
                               3896                 :            108 :     log_var(&arg1, &arg2, &result);
                               3897                 :                : 
                               3898                 :             78 :     res = make_result(&result);
                               3899                 :                : 
                               3900                 :             78 :     free_var(&result);
                               3901                 :                : 
 9170 tgl@sss.pgh.pa.us        3902                 :             78 :     PG_RETURN_NUMERIC(res);
                               3903                 :                : }
                               3904                 :                : 
                               3905                 :                : 
                               3906                 :                : /*
                               3907                 :                :  * numeric_power() -
                               3908                 :                :  *
                               3909                 :                :  *  Raise x to the power of y
                               3910                 :                :  */
                               3911                 :                : Datum
                               3912                 :            822 : numeric_power(PG_FUNCTION_ARGS)
                               3913                 :                : {
                               3914                 :            822 :     Numeric     num1 = PG_GETARG_NUMERIC(0);
                               3915                 :            822 :     Numeric     num2 = PG_GETARG_NUMERIC(1);
                               3916                 :                :     Numeric     res;
                               3917                 :                :     NumericVar  arg1;
                               3918                 :                :     NumericVar  arg2;
                               3919                 :                :     NumericVar  result;
                               3920                 :                :     int         sign1,
                               3921                 :                :                 sign2;
                               3922                 :                : 
                               3923                 :                :     /*
                               3924                 :                :      * Handle NaN and infinities
                               3925                 :                :      */
 1872                          3926   [ +  +  +  + ]:            822 :     if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
                               3927                 :                :     {
                               3928                 :                :         /*
                               3929                 :                :          * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
                               3930                 :                :          * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
                               3931                 :                :          * (with no error).
                               3932                 :                :          */
                               3933         [ +  + ]:            117 :         if (NUMERIC_IS_NAN(num1))
                               3934                 :                :         {
                               3935         [ +  + ]:             27 :             if (!NUMERIC_IS_SPECIAL(num2))
                               3936                 :                :             {
                               3937                 :             18 :                 init_var_from_num(num2, &arg2);
                               3938         [ +  + ]:             18 :                 if (cmp_var(&arg2, &const_zero) == 0)
                               3939                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_one));
                               3940                 :                :             }
                               3941                 :             21 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3942                 :                :         }
                               3943         [ +  + ]:             90 :         if (NUMERIC_IS_NAN(num2))
                               3944                 :                :         {
                               3945         [ +  + ]:             21 :             if (!NUMERIC_IS_SPECIAL(num1))
                               3946                 :                :             {
                               3947                 :             18 :                 init_var_from_num(num1, &arg1);
                               3948         [ +  + ]:             18 :                 if (cmp_var(&arg1, &const_one) == 0)
                               3949                 :              6 :                     PG_RETURN_NUMERIC(make_result(&const_one));
                               3950                 :                :             }
                               3951                 :             15 :             PG_RETURN_NUMERIC(make_result(&const_nan));
                               3952                 :                :         }
                               3953                 :                :         /* At least one input is infinite, but error rules still apply */
                               3954                 :             69 :         sign1 = numeric_sign_internal(num1);
                               3955                 :             69 :         sign2 = numeric_sign_internal(num2);
                               3956   [ +  +  +  + ]:             69 :         if (sign1 == 0 && sign2 < 0)
                               3957         [ +  - ]:              3 :             ereport(ERROR,
                               3958                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               3959                 :                :                      errmsg("zero raised to a negative power is undefined")));
                               3960   [ +  +  +  + ]:             66 :         if (sign1 < 0 && !numeric_is_integral(num2))
                               3961         [ +  - ]:              3 :             ereport(ERROR,
                               3962                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               3963                 :                :                      errmsg("a negative number raised to a non-integer power yields a complex result")));
                               3964                 :                : 
                               3965                 :                :         /*
                               3966                 :                :          * POSIX gives this series of rules for pow(3) with infinite inputs:
                               3967                 :                :          *
                               3968                 :                :          * For any value of y, if x is +1, 1.0 shall be returned.
                               3969                 :                :          */
                               3970         [ +  + ]:             63 :         if (!NUMERIC_IS_SPECIAL(num1))
                               3971                 :                :         {
                               3972                 :             21 :             init_var_from_num(num1, &arg1);
                               3973         [ +  + ]:             21 :             if (cmp_var(&arg1, &const_one) == 0)
 2669                          3974                 :              3 :                 PG_RETURN_NUMERIC(make_result(&const_one));
                               3975                 :                :         }
                               3976                 :                : 
                               3977                 :                :         /*
                               3978                 :                :          * For any value of x, if y is [-]0, 1.0 shall be returned.
                               3979                 :                :          */
 1872                          3980         [ +  + ]:             60 :         if (sign2 == 0)
 2669                          3981                 :              6 :             PG_RETURN_NUMERIC(make_result(&const_one));
                               3982                 :                : 
                               3983                 :                :         /*
                               3984                 :                :          * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
                               3985                 :                :          * returned.  For y > 0 and not an odd integer, if x is [-]0, +0 shall
                               3986                 :                :          * be returned.  (Since we don't deal in minus zero, we need not
                               3987                 :                :          * distinguish these two cases.)
                               3988                 :                :          */
 1872                          3989   [ +  +  +  - ]:             54 :         if (sign1 == 0 && sign2 > 0)
                               3990                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               3991                 :                : 
                               3992                 :                :         /*
                               3993                 :                :          * If x is -1, and y is [-]Inf, 1.0 shall be returned.
                               3994                 :                :          *
                               3995                 :                :          * For |x| < 1, if y is -Inf, +Inf shall be returned.
                               3996                 :                :          *
                               3997                 :                :          * For |x| > 1, if y is -Inf, +0 shall be returned.
                               3998                 :                :          *
                               3999                 :                :          * For |x| < 1, if y is +Inf, +0 shall be returned.
                               4000                 :                :          *
                               4001                 :                :          * For |x| > 1, if y is +Inf, +Inf shall be returned.
                               4002                 :                :          */
                               4003         [ +  + ]:             51 :         if (NUMERIC_IS_INF(num2))
                               4004                 :                :         {
                               4005                 :                :             bool        abs_x_gt_one;
                               4006                 :                : 
                               4007         [ +  + ]:             27 :             if (NUMERIC_IS_SPECIAL(num1))
                               4008                 :             12 :                 abs_x_gt_one = true;    /* x is either Inf or -Inf */
                               4009                 :                :             else
                               4010                 :                :             {
                               4011                 :             15 :                 init_var_from_num(num1, &arg1);
                               4012         [ +  + ]:             15 :                 if (cmp_var(&arg1, &const_minus_one) == 0)
                               4013                 :              3 :                     PG_RETURN_NUMERIC(make_result(&const_one));
                               4014                 :             12 :                 arg1.sign = NUMERIC_POS;    /* now arg1 = abs(x) */
                               4015                 :             12 :                 abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
                               4016                 :                :             }
                               4017         [ +  + ]:             24 :             if (abs_x_gt_one == (sign2 > 0))
                               4018                 :             15 :                 PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4019                 :                :             else
                               4020                 :              9 :                 PG_RETURN_NUMERIC(make_result(&const_zero));
                               4021                 :                :         }
                               4022                 :                : 
                               4023                 :                :         /*
                               4024                 :                :          * For y < 0, if x is +Inf, +0 shall be returned.
                               4025                 :                :          *
                               4026                 :                :          * For y > 0, if x is +Inf, +Inf shall be returned.
                               4027                 :                :          */
                               4028         [ +  + ]:             24 :         if (NUMERIC_IS_PINF(num1))
                               4029                 :                :         {
                               4030         [ +  + ]:             12 :             if (sign2 > 0)
                               4031                 :              9 :                 PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4032                 :                :             else
                               4033                 :              3 :                 PG_RETURN_NUMERIC(make_result(&const_zero));
                               4034                 :                :         }
                               4035                 :                : 
                               4036         [ -  + ]:             12 :         Assert(NUMERIC_IS_NINF(num1));
                               4037                 :                : 
                               4038                 :                :         /*
                               4039                 :                :          * For y an odd integer < 0, if x is -Inf, -0 shall be returned.  For
                               4040                 :                :          * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
                               4041                 :                :          * (Again, we need not distinguish these two cases.)
                               4042                 :                :          */
                               4043         [ +  + ]:             12 :         if (sign2 < 0)
                               4044                 :              6 :             PG_RETURN_NUMERIC(make_result(&const_zero));
                               4045                 :                : 
                               4046                 :                :         /*
                               4047                 :                :          * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
                               4048                 :                :          * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
                               4049                 :                :          */
                               4050                 :              6 :         init_var_from_num(num2, &arg2);
                               4051   [ +  -  +  - ]:              6 :         if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
                               4052         [ +  + ]:              6 :             (arg2.digits[arg2.ndigits - 1] & 1))
                               4053                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
                               4054                 :                :         else
                               4055                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4056                 :                :     }
                               4057                 :                : 
                               4058                 :                :     /*
                               4059                 :                :      * The SQL spec requires that we emit a particular SQLSTATE error code for
                               4060                 :                :      * certain error conditions.  Specifically, we don't return a
                               4061                 :                :      * divide-by-zero error code for 0 ^ -1.  Raising a negative number to a
                               4062                 :                :      * non-integer power must produce the same error code, but that case is
                               4063                 :                :      * handled in power_var().
                               4064                 :                :      */
                               4065                 :            705 :     sign1 = numeric_sign_internal(num1);
                               4066                 :            705 :     sign2 = numeric_sign_internal(num2);
                               4067                 :                : 
                               4068   [ +  +  +  + ]:            705 :     if (sign1 == 0 && sign2 < 0)
 7783 neilc@samurai.com        4069         [ +  - ]:              6 :         ereport(ERROR,
                               4070                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               4071                 :                :                  errmsg("zero raised to a negative power is undefined")));
                               4072                 :                : 
                               4073                 :                :     /*
                               4074                 :                :      * Initialize things
                               4075                 :                :      */
 1872 tgl@sss.pgh.pa.us        4076                 :            699 :     init_var(&result);
                               4077                 :            699 :     init_var_from_num(num1, &arg1);
                               4078                 :            699 :     init_var_from_num(num2, &arg2);
                               4079                 :                : 
                               4080                 :                :     /*
                               4081                 :                :      * Call power_var() to compute and return the result; note it handles
                               4082                 :                :      * scale selection itself.
                               4083                 :                :      */
 9747 JanWieck@Yahoo.com       4084                 :            699 :     power_var(&arg1, &arg2, &result);
                               4085                 :                : 
                               4086                 :            684 :     res = make_result(&result);
                               4087                 :                : 
                               4088                 :            684 :     free_var(&result);
                               4089                 :                : 
 9170 tgl@sss.pgh.pa.us        4090                 :            684 :     PG_RETURN_NUMERIC(res);
                               4091                 :                : }
                               4092                 :                : 
                               4093                 :                : /*
                               4094                 :                :  * numeric_scale() -
                               4095                 :                :  *
                               4096                 :                :  *  Returns the scale, i.e. the count of decimal digits in the fractional part
                               4097                 :                :  */
                               4098                 :                : Datum
 3532 alvherre@alvh.no-ip.     4099                 :             54 : numeric_scale(PG_FUNCTION_ARGS)
                               4100                 :                : {
                               4101                 :             54 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4102                 :                : 
 1872 tgl@sss.pgh.pa.us        4103         [ +  + ]:             54 :     if (NUMERIC_IS_SPECIAL(num))
 3532 alvherre@alvh.no-ip.     4104                 :              9 :         PG_RETURN_NULL();
                               4105                 :                : 
                               4106         [ +  - ]:             45 :     PG_RETURN_INT32(NUMERIC_DSCALE(num));
                               4107                 :                : }
                               4108                 :                : 
                               4109                 :                : /*
                               4110                 :                :  * Calculate minimum scale for value.
                               4111                 :                :  */
                               4112                 :                : static int
 2070 tgl@sss.pgh.pa.us        4113                 :            186 : get_min_scale(NumericVar *var)
                               4114                 :                : {
                               4115                 :                :     int         min_scale;
                               4116                 :                :     int         last_digit_pos;
                               4117                 :                : 
                               4118                 :                :     /*
                               4119                 :                :      * Ordinarily, the input value will be "stripped" so that the last
                               4120                 :                :      * NumericDigit is nonzero.  But we don't want to get into an infinite
                               4121                 :                :      * loop if it isn't, so explicitly find the last nonzero digit.
                               4122                 :                :      */
                               4123                 :            186 :     last_digit_pos = var->ndigits - 1;
                               4124         [ +  + ]:            186 :     while (last_digit_pos >= 0 &&
                               4125         [ -  + ]:            171 :            var->digits[last_digit_pos] == 0)
 2070 tgl@sss.pgh.pa.us        4126                 :UBC           0 :         last_digit_pos--;
                               4127                 :                : 
 2070 tgl@sss.pgh.pa.us        4128         [ +  + ]:CBC         186 :     if (last_digit_pos >= 0)
                               4129                 :                :     {
                               4130                 :                :         /* compute min_scale assuming that last ndigit has no zeroes */
                               4131                 :            171 :         min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
                               4132                 :                : 
                               4133                 :                :         /*
                               4134                 :                :          * We could get a negative result if there are no digits after the
                               4135                 :                :          * decimal point.  In this case the min_scale must be zero.
                               4136                 :                :          */
                               4137         [ +  + ]:            171 :         if (min_scale > 0)
                               4138                 :                :         {
                               4139                 :                :             /*
                               4140                 :                :              * Reduce min_scale if trailing digit(s) in last NumericDigit are
                               4141                 :                :              * zero.
                               4142                 :                :              */
                               4143                 :             93 :             NumericDigit last_digit = var->digits[last_digit_pos];
                               4144                 :                : 
                               4145         [ +  + ]:            249 :             while (last_digit % 10 == 0)
                               4146                 :                :             {
                               4147                 :            156 :                 min_scale--;
                               4148                 :            156 :                 last_digit /= 10;
                               4149                 :                :             }
                               4150                 :                :         }
                               4151                 :                :         else
                               4152                 :             78 :             min_scale = 0;
                               4153                 :                :     }
                               4154                 :                :     else
                               4155                 :             15 :         min_scale = 0;          /* result if input is zero */
                               4156                 :                : 
                               4157                 :            186 :     return min_scale;
                               4158                 :                : }
                               4159                 :                : 
                               4160                 :                : /*
                               4161                 :                :  * Returns minimum scale required to represent supplied value without loss.
                               4162                 :                :  */
                               4163                 :                : Datum
                               4164                 :             36 : numeric_min_scale(PG_FUNCTION_ARGS)
                               4165                 :                : {
                               4166                 :             36 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4167                 :                :     NumericVar  arg;
                               4168                 :                :     int         min_scale;
                               4169                 :                : 
 1872                          4170         [ +  + ]:             36 :     if (NUMERIC_IS_SPECIAL(num))
 2070                          4171                 :              6 :         PG_RETURN_NULL();
                               4172                 :                : 
                               4173                 :             30 :     init_var_from_num(num, &arg);
                               4174                 :             30 :     min_scale = get_min_scale(&arg);
                               4175                 :             30 :     free_var(&arg);
                               4176                 :                : 
                               4177                 :             30 :     PG_RETURN_INT32(min_scale);
                               4178                 :                : }
                               4179                 :                : 
                               4180                 :                : /*
                               4181                 :                :  * Reduce scale of numeric value to represent supplied value without loss.
                               4182                 :                :  */
                               4183                 :                : Datum
                               4184                 :            162 : numeric_trim_scale(PG_FUNCTION_ARGS)
                               4185                 :                : {
                               4186                 :            162 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4187                 :                :     Numeric     res;
                               4188                 :                :     NumericVar  result;
                               4189                 :                : 
 1872                          4190         [ +  + ]:            162 :     if (NUMERIC_IS_SPECIAL(num))
                               4191                 :              6 :         PG_RETURN_NUMERIC(duplicate_numeric(num));
                               4192                 :                : 
 2070                          4193                 :            156 :     init_var_from_num(num, &result);
                               4194                 :            156 :     result.dscale = get_min_scale(&result);
                               4195                 :            156 :     res = make_result(&result);
                               4196                 :            156 :     free_var(&result);
                               4197                 :                : 
                               4198                 :            156 :     PG_RETURN_NUMERIC(res);
                               4199                 :                : }
                               4200                 :                : 
                               4201                 :                : /*
                               4202                 :                :  * Return a random numeric value in the range [rmin, rmax].
                               4203                 :                :  */
                               4204                 :                : Numeric
  528 dean.a.rasheed@gmail     4205                 :          16731 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
                               4206                 :                : {
                               4207                 :                :     NumericVar  rmin_var;
                               4208                 :                :     NumericVar  rmax_var;
                               4209                 :                :     NumericVar  result;
                               4210                 :                :     Numeric     res;
                               4211                 :                : 
                               4212                 :                :     /* Range bounds must not be NaN/infinity */
                               4213         [ +  + ]:          16731 :     if (NUMERIC_IS_SPECIAL(rmin))
                               4214                 :                :     {
                               4215         [ +  + ]:              6 :         if (NUMERIC_IS_NAN(rmin))
                               4216         [ +  - ]:              3 :             ereport(ERROR,
                               4217                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4218                 :                :                     errmsg("lower bound cannot be NaN"));
                               4219                 :                :         else
                               4220         [ +  - ]:              3 :             ereport(ERROR,
                               4221                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4222                 :                :                     errmsg("lower bound cannot be infinity"));
                               4223                 :                :     }
                               4224         [ +  + ]:          16725 :     if (NUMERIC_IS_SPECIAL(rmax))
                               4225                 :                :     {
                               4226         [ +  + ]:              6 :         if (NUMERIC_IS_NAN(rmax))
                               4227         [ +  - ]:              3 :             ereport(ERROR,
                               4228                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4229                 :                :                     errmsg("upper bound cannot be NaN"));
                               4230                 :                :         else
                               4231         [ +  - ]:              3 :             ereport(ERROR,
                               4232                 :                :                     errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4233                 :                :                     errmsg("upper bound cannot be infinity"));
                               4234                 :                :     }
                               4235                 :                : 
                               4236                 :                :     /* Return a random value in the range [rmin, rmax] */
                               4237                 :          16719 :     init_var_from_num(rmin, &rmin_var);
                               4238                 :          16719 :     init_var_from_num(rmax, &rmax_var);
                               4239                 :                : 
                               4240                 :          16719 :     init_var(&result);
                               4241                 :                : 
                               4242                 :          16719 :     random_var(state, &rmin_var, &rmax_var, &result);
                               4243                 :                : 
                               4244                 :          16716 :     res = make_result(&result);
                               4245                 :                : 
                               4246                 :          16716 :     free_var(&result);
                               4247                 :                : 
                               4248                 :          16716 :     return res;
                               4249                 :                : }
                               4250                 :                : 
                               4251                 :                : 
                               4252                 :                : /* ----------------------------------------------------------------------
                               4253                 :                :  *
                               4254                 :                :  * Type conversion functions
                               4255                 :                :  *
                               4256                 :                :  * ----------------------------------------------------------------------
                               4257                 :                :  */
                               4258                 :                : 
                               4259                 :                : Numeric
 1823 peter@eisentraut.org     4260                 :         933893 : int64_to_numeric(int64 val)
                               4261                 :                : {
                               4262                 :                :     Numeric     res;
                               4263                 :                :     NumericVar  result;
                               4264                 :                : 
 9747 JanWieck@Yahoo.com       4265                 :         933893 :     init_var(&result);
                               4266                 :                : 
 1823 peter@eisentraut.org     4267                 :         933893 :     int64_to_numericvar(val, &result);
                               4268                 :                : 
 9747 JanWieck@Yahoo.com       4269                 :         933893 :     res = make_result(&result);
                               4270                 :                : 
                               4271                 :         933893 :     free_var(&result);
                               4272                 :                : 
 1823 peter@eisentraut.org     4273                 :         933893 :     return res;
                               4274                 :                : }
                               4275                 :                : 
                               4276                 :                : /*
                               4277                 :                :  * Convert val1/(10**log10val2) to numeric.  This is much faster than normal
                               4278                 :                :  * numeric division.
                               4279                 :                :  */
                               4280                 :                : Numeric
 1614                          4281                 :          14694 : int64_div_fast_to_numeric(int64 val1, int log10val2)
                               4282                 :                : {
                               4283                 :                :     Numeric     res;
                               4284                 :                :     NumericVar  result;
                               4285                 :                :     int         rscale;
                               4286                 :                :     int         w;
                               4287                 :                :     int         m;
                               4288                 :                : 
  946 dean.a.rasheed@gmail     4289                 :          14694 :     init_var(&result);
                               4290                 :                : 
                               4291                 :                :     /* result scale */
                               4292                 :          14694 :     rscale = log10val2 < 0 ? 0 : log10val2;
                               4293                 :                : 
                               4294                 :                :     /* how much to decrease the weight by */
 1614 peter@eisentraut.org     4295                 :          14694 :     w = log10val2 / DEC_DIGITS;
                               4296                 :                :     /* how much is left to divide by */
                               4297                 :          14694 :     m = log10val2 % DEC_DIGITS;
  946 dean.a.rasheed@gmail     4298         [ -  + ]:          14694 :     if (m < 0)
                               4299                 :                :     {
  946 dean.a.rasheed@gmail     4300                 :UBC           0 :         m += DEC_DIGITS;
                               4301                 :              0 :         w--;
                               4302                 :                :     }
                               4303                 :                : 
                               4304                 :                :     /*
                               4305                 :                :      * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
                               4306                 :                :      * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
                               4307                 :                :      * one more.
                               4308                 :                :      */
 1614 peter@eisentraut.org     4309         [ +  - ]:CBC       14694 :     if (m > 0)
                               4310                 :                :     {
                               4311                 :                : #if DEC_DIGITS == 4
                               4312                 :                :         static const int pow10[] = {1, 10, 100, 1000};
                               4313                 :                : #elif DEC_DIGITS == 2
                               4314                 :                :         static const int pow10[] = {1, 10};
                               4315                 :                : #elif DEC_DIGITS == 1
                               4316                 :                :         static const int pow10[] = {1};
                               4317                 :                : #else
                               4318                 :                : #error unsupported NBASE
                               4319                 :                : #endif
  946 dean.a.rasheed@gmail     4320                 :          14694 :         int64       factor = pow10[DEC_DIGITS - m];
                               4321                 :                :         int64       new_val1;
                               4322                 :                : 
                               4323                 :                :         StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
                               4324                 :                : 
                               4325         [ +  + ]:          14694 :         if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
                               4326                 :                :         {
                               4327                 :                :             /* do the multiplication using 128-bit integers */
                               4328                 :                :             INT128      tmp;
                               4329                 :                : 
   30 dean.a.rasheed@gmail     4330                 :GNC           6 :             tmp = int64_to_int128(0);
                               4331                 :              6 :             int128_add_int64_mul_int64(&tmp, val1, factor);
                               4332                 :                : 
  946 dean.a.rasheed@gmail     4333                 :CBC           6 :             int128_to_numericvar(tmp, &result);
                               4334                 :                :         }
                               4335                 :                :         else
                               4336                 :          14688 :             int64_to_numericvar(new_val1, &result);
                               4337                 :                : 
 1614 peter@eisentraut.org     4338                 :          14694 :         w++;
                               4339                 :                :     }
                               4340                 :                :     else
  946 dean.a.rasheed@gmail     4341                 :UBC           0 :         int64_to_numericvar(val1, &result);
                               4342                 :                : 
 1614 peter@eisentraut.org     4343                 :CBC       14694 :     result.weight -= w;
  946 dean.a.rasheed@gmail     4344                 :          14694 :     result.dscale = rscale;
                               4345                 :                : 
 1614 peter@eisentraut.org     4346                 :          14694 :     res = make_result(&result);
                               4347                 :                : 
                               4348                 :          14694 :     free_var(&result);
                               4349                 :                : 
                               4350                 :          14694 :     return res;
                               4351                 :                : }
                               4352                 :                : 
                               4353                 :                : Datum
 1823                          4354                 :         777183 : int4_numeric(PG_FUNCTION_ARGS)
                               4355                 :                : {
                               4356                 :         777183 :     int32       val = PG_GETARG_INT32(0);
                               4357                 :                : 
                               4358                 :         777183 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
                               4359                 :                : }
                               4360                 :                : 
                               4361                 :                : /*
                               4362                 :                :  * Internal version of int4_numeric() with support for soft error reporting.
                               4363                 :                :  */
                               4364                 :                : int32
    1 michael@paquier.xyz      4365                 :GNC        3842 : numeric_int4_safe(Numeric num, Node *escontext)
                               4366                 :                : {
                               4367                 :                :     NumericVar  x;
                               4368                 :                :     int32       result;
                               4369                 :                : 
 1872 tgl@sss.pgh.pa.us        4370         [ +  + ]:CBC        3842 :     if (NUMERIC_IS_SPECIAL(num))
                               4371                 :                :     {
    1 michael@paquier.xyz      4372         [ +  + ]:GNC           9 :         if (NUMERIC_IS_NAN(num))
                               4373         [ +  - ]:              3 :             ereturn(escontext, 0,
                               4374                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4375                 :                :                      errmsg("cannot convert NaN to %s", "integer")));
                               4376                 :                :         else
                               4377         [ +  - ]:              6 :             ereturn(escontext, 0,
                               4378                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4379                 :                :                      errmsg("cannot convert infinity to %s", "integer")));
                               4380                 :                :     }
                               4381                 :                : 
                               4382                 :                :     /* Convert to variable format, then convert to int4 */
 4672 heikki.linnakangas@i     4383                 :CBC        3833 :     init_var_from_num(num, &x);
                               4384                 :                : 
 2366 akorotkov@postgresql     4385         [ +  + ]:           3833 :     if (!numericvar_to_int32(&x, &result))
    1 michael@paquier.xyz      4386         [ +  + ]:GNC          45 :         ereturn(escontext, 0,
                               4387                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4388                 :                :                  errmsg("integer out of range")));
                               4389                 :                : 
 2366 akorotkov@postgresql     4390                 :CBC        3788 :     return result;
                               4391                 :                : }
                               4392                 :                : 
                               4393                 :                : Datum
                               4394                 :           3050 : numeric_int4(PG_FUNCTION_ARGS)
                               4395                 :                : {
                               4396                 :           3050 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4397                 :                : 
    1 michael@paquier.xyz      4398                 :GNC        3050 :     PG_RETURN_INT32(numeric_int4_safe(num, NULL));
                               4399                 :                : }
                               4400                 :                : 
                               4401                 :                : /*
                               4402                 :                :  * Given a NumericVar, convert it to an int32. If the NumericVar
                               4403                 :                :  * exceeds the range of an int32, false is returned, otherwise true is returned.
                               4404                 :                :  * The input NumericVar is *not* free'd.
                               4405                 :                :  */
                               4406                 :                : static bool
 2366 akorotkov@postgresql     4407                 :CBC        4205 : numericvar_to_int32(const NumericVar *var, int32 *result)
                               4408                 :                : {
                               4409                 :                :     int64       val;
                               4410                 :                : 
 3823 andres@anarazel.de       4411         [ +  + ]:           4205 :     if (!numericvar_to_int64(var, &val))
 2366 akorotkov@postgresql     4412                 :              3 :         return false;
                               4413                 :                : 
 1492 dean.a.rasheed@gmail     4414   [ +  +  +  + ]:           4202 :     if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
                               4415                 :             42 :         return false;
                               4416                 :                : 
                               4417                 :                :     /* Down-convert to int4 */
 2366 akorotkov@postgresql     4418                 :           4160 :     *result = (int32) val;
                               4419                 :                : 
 1492 dean.a.rasheed@gmail     4420                 :           4160 :     return true;
                               4421                 :                : }
                               4422                 :                : 
                               4423                 :                : Datum
 9182 tgl@sss.pgh.pa.us        4424                 :          18425 : int8_numeric(PG_FUNCTION_ARGS)
                               4425                 :                : {
 8205                          4426                 :          18425 :     int64       val = PG_GETARG_INT64(0);
                               4427                 :                : 
 1823 peter@eisentraut.org     4428                 :          18425 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
                               4429                 :                : }
                               4430                 :                : 
                               4431                 :                : /*
                               4432                 :                :  * Internal version of int8_numeric() with support for soft error reporting.
                               4433                 :                :  */
                               4434                 :                : int64
    1 michael@paquier.xyz      4435                 :GNC         285 : numeric_int8_safe(Numeric num, Node *escontext)
                               4436                 :                : {
                               4437                 :                :     NumericVar  x;
                               4438                 :                :     int64       result;
                               4439                 :                : 
 1872 tgl@sss.pgh.pa.us        4440         [ +  + ]:CBC         285 :     if (NUMERIC_IS_SPECIAL(num))
                               4441                 :                :     {
    1 michael@paquier.xyz      4442         [ +  + ]:GNC           9 :         if (NUMERIC_IS_NAN(num))
                               4443         [ +  - ]:              3 :             ereturn(escontext, 0,
                               4444                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4445                 :                :                      errmsg("cannot convert NaN to %s", "bigint")));
                               4446                 :                :         else
                               4447         [ +  - ]:              6 :             ereturn(escontext, 0,
                               4448                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4449                 :                :                      errmsg("cannot convert infinity to %s", "bigint")));
                               4450                 :                :     }
                               4451                 :                : 
                               4452                 :                :     /* Convert to variable format, then convert to int8 */
 4672 heikki.linnakangas@i     4453                 :CBC         276 :     init_var_from_num(num, &x);
                               4454                 :                : 
 3823 andres@anarazel.de       4455         [ +  + ]:            276 :     if (!numericvar_to_int64(&x, &result))
    1 michael@paquier.xyz      4456         [ +  + ]:GNC          30 :         ereturn(escontext, 0,
                               4457                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4458                 :                :                  errmsg("bigint out of range")));
                               4459                 :                : 
  612 peter@eisentraut.org     4460                 :CBC         246 :     return result;
                               4461                 :                : }
                               4462                 :                : 
                               4463                 :                : Datum
                               4464                 :            261 : numeric_int8(PG_FUNCTION_ARGS)
                               4465                 :                : {
                               4466                 :            261 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4467                 :                : 
    1 michael@paquier.xyz      4468                 :GNC         261 :     PG_RETURN_INT64(numeric_int8_safe(num, NULL));
                               4469                 :                : }
                               4470                 :                : 
                               4471                 :                : 
                               4472                 :                : Datum
 9224 tgl@sss.pgh.pa.us        4473                 :CBC           3 : int2_numeric(PG_FUNCTION_ARGS)
                               4474                 :                : {
                               4475                 :              3 :     int16       val = PG_GETARG_INT16(0);
                               4476                 :                : 
 1823 peter@eisentraut.org     4477                 :              3 :     PG_RETURN_NUMERIC(int64_to_numeric(val));
                               4478                 :                : }
                               4479                 :                : 
                               4480                 :                : 
                               4481                 :                : Datum
 9224 tgl@sss.pgh.pa.us        4482                 :             51 : numeric_int2(PG_FUNCTION_ARGS)
                               4483                 :                : {
                               4484                 :             51 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4485                 :                :     NumericVar  x;
                               4486                 :                :     int64       val;
                               4487                 :                :     int16       result;
                               4488                 :                : 
 1872                          4489         [ +  + ]:             51 :     if (NUMERIC_IS_SPECIAL(num))
                               4490                 :                :     {
                               4491         [ +  + ]:              9 :         if (NUMERIC_IS_NAN(num))
                               4492         [ +  - ]:              3 :             ereport(ERROR,
                               4493                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4494                 :                :                      errmsg("cannot convert NaN to %s", "smallint")));
                               4495                 :                :         else
                               4496         [ +  - ]:              6 :             ereport(ERROR,
                               4497                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4498                 :                :                      errmsg("cannot convert infinity to %s", "smallint")));
                               4499                 :                :     }
                               4500                 :                : 
                               4501                 :                :     /* Convert to variable format and thence to int8 */
 4672 heikki.linnakangas@i     4502                 :             42 :     init_var_from_num(num, &x);
                               4503                 :                : 
 3823 andres@anarazel.de       4504         [ -  + ]:             42 :     if (!numericvar_to_int64(&x, &val))
 8077 tgl@sss.pgh.pa.us        4505         [ #  # ]:UBC           0 :         ereport(ERROR,
                               4506                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4507                 :                :                  errmsg("smallint out of range")));
                               4508                 :                : 
 1492 dean.a.rasheed@gmail     4509   [ +  +  +  + ]:CBC          42 :     if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
 8077 tgl@sss.pgh.pa.us        4510         [ +  - ]:              6 :         ereport(ERROR,
                               4511                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               4512                 :                :                  errmsg("smallint out of range")));
                               4513                 :                : 
                               4514                 :                :     /* Down-convert to int2 */
 1492 dean.a.rasheed@gmail     4515                 :             36 :     result = (int16) val;
                               4516                 :                : 
 8205 tgl@sss.pgh.pa.us        4517                 :             36 :     PG_RETURN_INT16(result);
                               4518                 :                : }
                               4519                 :                : 
                               4520                 :                : 
                               4521                 :                : Datum
 9170                          4522                 :            537 : float8_numeric(PG_FUNCTION_ARGS)
                               4523                 :                : {
                               4524                 :            537 :     float8      val = PG_GETARG_FLOAT8(0);
                               4525                 :                :     Numeric     res;
                               4526                 :                :     NumericVar  result;
                               4527                 :                :     char        buf[DBL_DIG + 100];
                               4528                 :                :     const char *endptr;
                               4529                 :                : 
                               4530         [ +  + ]:            537 :     if (isnan(val))
                               4531                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               4532                 :                : 
 2901                          4533         [ +  + ]:            534 :     if (isinf(val))
                               4534                 :                :     {
 1872                          4535         [ +  + ]:              6 :         if (val < 0)
                               4536                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
                               4537                 :                :         else
                               4538                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4539                 :                :     }
                               4540                 :                : 
 2901                          4541                 :            528 :     snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
                               4542                 :                : 
 9747 JanWieck@Yahoo.com       4543                 :            528 :     init_var(&result);
                               4544                 :                : 
                               4545                 :                :     /* Assume we need not worry about leading/trailing spaces */
 1002 tgl@sss.pgh.pa.us        4546                 :            528 :     (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
                               4547                 :                : 
 9747 JanWieck@Yahoo.com       4548                 :            528 :     res = make_result(&result);
                               4549                 :                : 
                               4550                 :            528 :     free_var(&result);
                               4551                 :                : 
 9170 tgl@sss.pgh.pa.us        4552                 :            528 :     PG_RETURN_NUMERIC(res);
                               4553                 :                : }
                               4554                 :                : 
                               4555                 :                : 
                               4556                 :                : Datum
                               4557                 :         259964 : numeric_float8(PG_FUNCTION_ARGS)
                               4558                 :                : {
                               4559                 :         259964 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4560                 :                :     char       *tmp;
                               4561                 :                :     Datum       result;
                               4562                 :                : 
 1872                          4563         [ +  + ]:         259964 :     if (NUMERIC_IS_SPECIAL(num))
                               4564                 :                :     {
                               4565         [ +  + ]:             39 :         if (NUMERIC_IS_PINF(num))
                               4566                 :             12 :             PG_RETURN_FLOAT8(get_float8_infinity());
                               4567         [ +  + ]:             27 :         else if (NUMERIC_IS_NINF(num))
                               4568                 :             12 :             PG_RETURN_FLOAT8(-get_float8_infinity());
                               4569                 :                :         else
                               4570                 :             15 :             PG_RETURN_FLOAT8(get_float8_nan());
                               4571                 :                :     }
                               4572                 :                : 
 9216                          4573                 :         259925 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
                               4574                 :                :                                               NumericGetDatum(num)));
                               4575                 :                : 
 9167                          4576                 :         259925 :     result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
                               4577                 :                : 
 9747 JanWieck@Yahoo.com       4578                 :         259925 :     pfree(tmp);
                               4579                 :                : 
 9167 tgl@sss.pgh.pa.us        4580                 :         259925 :     PG_RETURN_DATUM(result);
                               4581                 :                : }
                               4582                 :                : 
                               4583                 :                : 
                               4584                 :                : /*
                               4585                 :                :  * Convert numeric to float8; if out of range, return +/- HUGE_VAL
                               4586                 :                :  *
                               4587                 :                :  * (internal helper function, not directly callable from SQL)
                               4588                 :                :  */
                               4589                 :                : Datum
 8729                          4590                 :             14 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
                               4591                 :                : {
                               4592                 :             14 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4593                 :                :     double      val;
                               4594                 :                : 
 1872                          4595         [ -  + ]:             14 :     if (NUMERIC_IS_SPECIAL(num))
                               4596                 :                :     {
 1872 tgl@sss.pgh.pa.us        4597         [ #  # ]:UBC           0 :         if (NUMERIC_IS_PINF(num))
                               4598                 :              0 :             val = HUGE_VAL;
                               4599         [ #  # ]:              0 :         else if (NUMERIC_IS_NINF(num))
                               4600                 :              0 :             val = -HUGE_VAL;
                               4601                 :                :         else
                               4602                 :              0 :             val = get_float8_nan();
                               4603                 :                :     }
                               4604                 :                :     else
                               4605                 :                :     {
                               4606                 :                :         NumericVar  x;
                               4607                 :                : 
 1872 tgl@sss.pgh.pa.us        4608                 :CBC          14 :         init_var_from_num(num, &x);
                               4609                 :             14 :         val = numericvar_to_double_no_overflow(&x);
                               4610                 :                :     }
                               4611                 :                : 
 8729                          4612                 :             14 :     PG_RETURN_FLOAT8(val);
                               4613                 :                : }
                               4614                 :                : 
                               4615                 :                : Datum
 9170                          4616                 :          11173 : float4_numeric(PG_FUNCTION_ARGS)
                               4617                 :                : {
                               4618                 :          11173 :     float4      val = PG_GETARG_FLOAT4(0);
                               4619                 :                :     Numeric     res;
                               4620                 :                :     NumericVar  result;
                               4621                 :                :     char        buf[FLT_DIG + 100];
                               4622                 :                :     const char *endptr;
                               4623                 :                : 
                               4624         [ +  + ]:          11173 :     if (isnan(val))
                               4625                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               4626                 :                : 
 2901                          4627         [ +  + ]:          11170 :     if (isinf(val))
                               4628                 :                :     {
 1872                          4629         [ +  + ]:              6 :         if (val < 0)
                               4630                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_ninf));
                               4631                 :                :         else
                               4632                 :              3 :             PG_RETURN_NUMERIC(make_result(&const_pinf));
                               4633                 :                :     }
                               4634                 :                : 
 2901                          4635                 :          11164 :     snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
                               4636                 :                : 
 9747 JanWieck@Yahoo.com       4637                 :          11164 :     init_var(&result);
                               4638                 :                : 
                               4639                 :                :     /* Assume we need not worry about leading/trailing spaces */
 1002 tgl@sss.pgh.pa.us        4640                 :          11164 :     (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
                               4641                 :                : 
 9747 JanWieck@Yahoo.com       4642                 :          11164 :     res = make_result(&result);
                               4643                 :                : 
                               4644                 :          11164 :     free_var(&result);
                               4645                 :                : 
 9170 tgl@sss.pgh.pa.us        4646                 :          11164 :     PG_RETURN_NUMERIC(res);
                               4647                 :                : }
                               4648                 :                : 
                               4649                 :                : 
                               4650                 :                : Datum
                               4651                 :           1228 : numeric_float4(PG_FUNCTION_ARGS)
                               4652                 :                : {
                               4653                 :           1228 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4654                 :                :     char       *tmp;
                               4655                 :                :     Datum       result;
                               4656                 :                : 
 1872                          4657         [ +  + ]:           1228 :     if (NUMERIC_IS_SPECIAL(num))
                               4658                 :                :     {
                               4659         [ +  + ]:             39 :         if (NUMERIC_IS_PINF(num))
                               4660                 :             12 :             PG_RETURN_FLOAT4(get_float4_infinity());
                               4661         [ +  + ]:             27 :         else if (NUMERIC_IS_NINF(num))
                               4662                 :             12 :             PG_RETURN_FLOAT4(-get_float4_infinity());
                               4663                 :                :         else
                               4664                 :             15 :             PG_RETURN_FLOAT4(get_float4_nan());
                               4665                 :                :     }
                               4666                 :                : 
 9216                          4667                 :           1189 :     tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
                               4668                 :                :                                               NumericGetDatum(num)));
                               4669                 :                : 
 9167                          4670                 :           1189 :     result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
                               4671                 :                : 
 9747 JanWieck@Yahoo.com       4672                 :           1189 :     pfree(tmp);
                               4673                 :                : 
 9167 tgl@sss.pgh.pa.us        4674                 :           1189 :     PG_RETURN_DATUM(result);
                               4675                 :                : }
                               4676                 :                : 
                               4677                 :                : 
                               4678                 :                : Datum
 1894 fujii@postgresql.org     4679                 :             60 : numeric_pg_lsn(PG_FUNCTION_ARGS)
                               4680                 :                : {
                               4681                 :             60 :     Numeric     num = PG_GETARG_NUMERIC(0);
                               4682                 :                :     NumericVar  x;
                               4683                 :                :     XLogRecPtr  result;
                               4684                 :                : 
 1872 tgl@sss.pgh.pa.us        4685         [ +  + ]:             60 :     if (NUMERIC_IS_SPECIAL(num))
                               4686                 :                :     {
                               4687         [ +  - ]:              3 :         if (NUMERIC_IS_NAN(num))
                               4688         [ +  - ]:              3 :             ereport(ERROR,
                               4689                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4690                 :                :                      errmsg("cannot convert NaN to %s", "pg_lsn")));
                               4691                 :                :         else
 1872 tgl@sss.pgh.pa.us        4692         [ #  # ]:UBC           0 :             ereport(ERROR,
                               4693                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               4694                 :                :                      errmsg("cannot convert infinity to %s", "pg_lsn")));
                               4695                 :                :     }
                               4696                 :                : 
                               4697                 :                :     /* Convert to variable format and thence to pg_lsn */
 1894 fujii@postgresql.org     4698                 :CBC          57 :     init_var_from_num(num, &x);
                               4699                 :                : 
                               4700         [ +  + ]:             57 :     if (!numericvar_to_uint64(&x, (uint64 *) &result))
                               4701         [ +  - ]:             12 :         ereport(ERROR,
                               4702                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4703                 :                :                  errmsg("pg_lsn out of range")));
                               4704                 :                : 
                               4705                 :             45 :     PG_RETURN_LSN(result);
                               4706                 :                : }
                               4707                 :                : 
                               4708                 :                : 
                               4709                 :                : /* ----------------------------------------------------------------------
                               4710                 :                :  *
                               4711                 :                :  * Aggregate functions
                               4712                 :                :  *
                               4713                 :                :  * The transition datatype for all these aggregates is declared as INTERNAL.
                               4714                 :                :  * Actually, it's a pointer to a NumericAggState allocated in the aggregate
                               4715                 :                :  * context.  The digit buffers for the NumericVars will be there too.
                               4716                 :                :  *
                               4717                 :                :  * For integer inputs, some aggregates use special-purpose 64-bit or 128-bit
                               4718                 :                :  * integer based transition datatypes to speed up calculations.
                               4719                 :                :  *
                               4720                 :                :  * ----------------------------------------------------------------------
                               4721                 :                :  */
                               4722                 :                : 
                               4723                 :                : typedef struct NumericAggState
                               4724                 :                : {
                               4725                 :                :     bool        calcSumX2;      /* if true, calculate sumX2 */
                               4726                 :                :     MemoryContext agg_context;  /* context we're calculating in */
                               4727                 :                :     int64       N;              /* count of processed numbers */
                               4728                 :                :     NumericSumAccum sumX;       /* sum of processed numbers */
                               4729                 :                :     NumericSumAccum sumX2;      /* sum of squares of processed numbers */
                               4730                 :                :     int         maxScale;       /* maximum scale seen so far */
                               4731                 :                :     int64       maxScaleCount;  /* number of values seen with maximum scale */
                               4732                 :                :     /* These counts are *not* included in N!  Use NA_TOTAL_COUNT() as needed */
                               4733                 :                :     int64       NaNcount;       /* count of NaN values */
                               4734                 :                :     int64       pInfcount;      /* count of +Inf values */
                               4735                 :                :     int64       nInfcount;      /* count of -Inf values */
                               4736                 :                : } NumericAggState;
                               4737                 :                : 
                               4738                 :                : #define NA_TOTAL_COUNT(na) \
                               4739                 :                :     ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
                               4740                 :                : 
                               4741                 :                : /*
                               4742                 :                :  * Prepare state data for a numeric aggregate function that needs to compute
                               4743                 :                :  * sum, count and optionally sum of squares of the input.
                               4744                 :                :  */
                               4745                 :                : static NumericAggState *
 4312 tgl@sss.pgh.pa.us        4746                 :          85570 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
                               4747                 :                : {
                               4748                 :                :     NumericAggState *state;
                               4749                 :                :     MemoryContext agg_context;
                               4750                 :                :     MemoryContext old_context;
                               4751                 :                : 
                               4752         [ -  + ]:          85570 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 4312 tgl@sss.pgh.pa.us        4753         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               4754                 :                : 
 4312 tgl@sss.pgh.pa.us        4755                 :CBC       85570 :     old_context = MemoryContextSwitchTo(agg_context);
                               4756                 :                : 
                               4757                 :          85570 :     state = (NumericAggState *) palloc0(sizeof(NumericAggState));
                               4758                 :          85570 :     state->calcSumX2 = calcSumX2;
                               4759                 :          85570 :     state->agg_context = agg_context;
                               4760                 :                : 
                               4761                 :          85570 :     MemoryContextSwitchTo(old_context);
                               4762                 :                : 
                               4763                 :          85570 :     return state;
                               4764                 :                : }
                               4765                 :                : 
                               4766                 :                : /*
                               4767                 :                :  * Like makeNumericAggState(), but allocate the state in the current memory
                               4768                 :                :  * context.
                               4769                 :                :  */
                               4770                 :                : static NumericAggState *
 3362                          4771                 :             42 : makeNumericAggStateCurrentContext(bool calcSumX2)
                               4772                 :                : {
                               4773                 :                :     NumericAggState *state;
                               4774                 :                : 
                               4775                 :             42 :     state = (NumericAggState *) palloc0(sizeof(NumericAggState));
                               4776                 :             42 :     state->calcSumX2 = calcSumX2;
                               4777                 :             42 :     state->agg_context = CurrentMemoryContext;
                               4778                 :                : 
                               4779                 :             42 :     return state;
                               4780                 :                : }
                               4781                 :                : 
                               4782                 :                : /*
                               4783                 :                :  * Accumulate a new input value for numeric aggregate functions.
                               4784                 :                :  */
                               4785                 :                : static void
 4312                          4786                 :        1056776 : do_numeric_accum(NumericAggState *state, Numeric newval)
                               4787                 :                : {
                               4788                 :                :     NumericVar  X;
                               4789                 :                :     NumericVar  X2;
                               4790                 :                :     MemoryContext old_context;
                               4791                 :                : 
                               4792                 :                :     /* Count NaN/infinity inputs separately from all else */
 1872                          4793         [ +  + ]:        1056776 :     if (NUMERIC_IS_SPECIAL(newval))
                               4794                 :                :     {
                               4795         [ +  + ]:             81 :         if (NUMERIC_IS_PINF(newval))
                               4796                 :             36 :             state->pInfcount++;
                               4797         [ +  + ]:             45 :         else if (NUMERIC_IS_NINF(newval))
                               4798                 :             18 :             state->nInfcount++;
                               4799                 :                :         else
                               4800                 :             27 :             state->NaNcount++;
 4312                          4801                 :             81 :         return;
                               4802                 :                :     }
                               4803                 :                : 
                               4804                 :                :     /* load processed number in short-lived context */
                               4805                 :        1056695 :     init_var_from_num(newval, &X);
                               4806                 :                : 
                               4807                 :                :     /*
                               4808                 :                :      * Track the highest input dscale that we've seen, to support inverse
                               4809                 :                :      * transitions (see do_numeric_discard).
                               4810                 :                :      */
 4165                          4811         [ +  + ]:        1056695 :     if (X.dscale > state->maxScale)
                               4812                 :                :     {
                               4813                 :             78 :         state->maxScale = X.dscale;
                               4814                 :             78 :         state->maxScaleCount = 1;
                               4815                 :                :     }
                               4816         [ +  + ]:        1056617 :     else if (X.dscale == state->maxScale)
                               4817                 :        1056599 :         state->maxScaleCount++;
                               4818                 :                : 
                               4819                 :                :     /* if we need X^2, calculate that in short-lived context */
 4312                          4820         [ +  + ]:        1056695 :     if (state->calcSumX2)
                               4821                 :                :     {
                               4822                 :         120366 :         init_var(&X2);
                               4823                 :         120366 :         mul_var(&X, &X, &X2, X.dscale * 2);
                               4824                 :                :     }
                               4825                 :                : 
                               4826                 :                :     /* The rest of this needs to work in the aggregate context */
                               4827                 :        1056695 :     old_context = MemoryContextSwitchTo(state->agg_context);
                               4828                 :                : 
 3291 heikki.linnakangas@i     4829                 :        1056695 :     state->N++;
                               4830                 :                : 
                               4831                 :                :     /* Accumulate sums */
                               4832                 :        1056695 :     accum_sum_add(&(state->sumX), &X);
                               4833                 :                : 
                               4834         [ +  + ]:        1056695 :     if (state->calcSumX2)
                               4835                 :         120366 :         accum_sum_add(&(state->sumX2), &X2);
                               4836                 :                : 
 4312 tgl@sss.pgh.pa.us        4837                 :        1056695 :     MemoryContextSwitchTo(old_context);
                               4838                 :                : }
                               4839                 :                : 
                               4840                 :                : /*
                               4841                 :                :  * Attempt to remove an input value from the aggregated state.
                               4842                 :                :  *
                               4843                 :                :  * If the value cannot be removed then the function will return false; the
                               4844                 :                :  * possible reasons for failing are described below.
                               4845                 :                :  *
                               4846                 :                :  * If we aggregate the values 1.01 and 2 then the result will be 3.01.
                               4847                 :                :  * If we are then asked to un-aggregate the 1.01 then we must fail as we
                               4848                 :                :  * won't be able to tell what the new aggregated value's dscale should be.
                               4849                 :                :  * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
                               4850                 :                :  * have been zero if we'd really aggregated only 2.
                               4851                 :                :  *
                               4852                 :                :  * Note: alternatively, we could count the number of inputs with each possible
                               4853                 :                :  * dscale (up to some sane limit).  Not yet clear if it's worth the trouble.
                               4854                 :                :  */
                               4855                 :                : static bool
 4165                          4856                 :            171 : do_numeric_discard(NumericAggState *state, Numeric newval)
                               4857                 :                : {
                               4858                 :                :     NumericVar  X;
                               4859                 :                :     NumericVar  X2;
                               4860                 :                :     MemoryContext old_context;
                               4861                 :                : 
                               4862                 :                :     /* Count NaN/infinity inputs separately from all else */
 1872                          4863         [ +  + ]:            171 :     if (NUMERIC_IS_SPECIAL(newval))
                               4864                 :                :     {
                               4865         [ -  + ]:              3 :         if (NUMERIC_IS_PINF(newval))
 1872 tgl@sss.pgh.pa.us        4866                 :UBC           0 :             state->pInfcount--;
 1872 tgl@sss.pgh.pa.us        4867         [ -  + ]:CBC           3 :         else if (NUMERIC_IS_NINF(newval))
 1872 tgl@sss.pgh.pa.us        4868                 :UBC           0 :             state->nInfcount--;
                               4869                 :                :         else
 1872 tgl@sss.pgh.pa.us        4870                 :CBC           3 :             state->NaNcount--;
 4165                          4871                 :              3 :         return true;
                               4872                 :                :     }
                               4873                 :                : 
                               4874                 :                :     /* load processed number in short-lived context */
                               4875                 :            168 :     init_var_from_num(newval, &X);
                               4876                 :                : 
                               4877                 :                :     /*
                               4878                 :                :      * state->sumX's dscale is the maximum dscale of any of the inputs.
                               4879                 :                :      * Removing the last input with that dscale would require us to recompute
                               4880                 :                :      * the maximum dscale of the *remaining* inputs, which we cannot do unless
                               4881                 :                :      * no more non-NaN inputs remain at all.  So we report a failure instead,
                               4882                 :                :      * and force the aggregation to be redone from scratch.
                               4883                 :                :      */
                               4884         [ +  - ]:            168 :     if (X.dscale == state->maxScale)
                               4885                 :                :     {
                               4886   [ +  +  +  + ]:            168 :         if (state->maxScaleCount > 1 || state->maxScale == 0)
                               4887                 :                :         {
                               4888                 :                :             /*
                               4889                 :                :              * Some remaining inputs have same dscale, or dscale hasn't gotten
                               4890                 :                :              * above zero anyway
                               4891                 :                :              */
                               4892                 :            159 :             state->maxScaleCount--;
                               4893                 :                :         }
                               4894         [ +  + ]:              9 :         else if (state->N == 1)
                               4895                 :                :         {
                               4896                 :                :             /* No remaining non-NaN inputs at all, so reset maxScale */
                               4897                 :              6 :             state->maxScale = 0;
                               4898                 :              6 :             state->maxScaleCount = 0;
                               4899                 :                :         }
                               4900                 :                :         else
                               4901                 :                :         {
                               4902                 :                :             /* Correct new maxScale is uncertain, must fail */
                               4903                 :              3 :             return false;
                               4904                 :                :         }
                               4905                 :                :     }
                               4906                 :                : 
                               4907                 :                :     /* if we need X^2, calculate that in short-lived context */
                               4908         [ +  + ]:            165 :     if (state->calcSumX2)
                               4909                 :                :     {
                               4910                 :            144 :         init_var(&X2);
                               4911                 :            144 :         mul_var(&X, &X, &X2, X.dscale * 2);
                               4912                 :                :     }
                               4913                 :                : 
                               4914                 :                :     /* The rest of this needs to work in the aggregate context */
                               4915                 :            165 :     old_context = MemoryContextSwitchTo(state->agg_context);
                               4916                 :                : 
                               4917         [ +  + ]:            165 :     if (state->N-- > 1)
                               4918                 :                :     {
                               4919                 :                :         /* Negate X, to subtract it from the sum */
 3291 heikki.linnakangas@i     4920         [ +  - ]:            156 :         X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
                               4921                 :            156 :         accum_sum_add(&(state->sumX), &X);
                               4922                 :                : 
 4165 tgl@sss.pgh.pa.us        4923         [ +  + ]:            156 :         if (state->calcSumX2)
                               4924                 :                :         {
                               4925                 :                :             /* Negate X^2. X^2 is always positive */
 3291 heikki.linnakangas@i     4926                 :            144 :             X2.sign = NUMERIC_NEG;
                               4927                 :            144 :             accum_sum_add(&(state->sumX2), &X2);
                               4928                 :                :         }
                               4929                 :                :     }
                               4930                 :                :     else
                               4931                 :                :     {
                               4932                 :                :         /* Zero the sums */
 4165 tgl@sss.pgh.pa.us        4933         [ -  + ]:              9 :         Assert(state->N == 0);
                               4934                 :                : 
 3291 heikki.linnakangas@i     4935                 :              9 :         accum_sum_reset(&state->sumX);
                               4936         [ -  + ]:              9 :         if (state->calcSumX2)
 3291 heikki.linnakangas@i     4937                 :UBC           0 :             accum_sum_reset(&state->sumX2);
                               4938                 :                :     }
                               4939                 :                : 
 4165 tgl@sss.pgh.pa.us        4940                 :CBC         165 :     MemoryContextSwitchTo(old_context);
                               4941                 :                : 
                               4942                 :            165 :     return true;
                               4943                 :                : }
                               4944                 :                : 
                               4945                 :                : /*
                               4946                 :                :  * Generic transition function for numeric aggregates that require sumX2.
                               4947                 :                :  */
                               4948                 :                : Datum
 9182                          4949                 :            321 : numeric_accum(PG_FUNCTION_ARGS)
                               4950                 :                : {
                               4951                 :                :     NumericAggState *state;
                               4952                 :                : 
 4312                          4953         [ +  + ]:            321 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               4954                 :                : 
                               4955                 :                :     /* Create the state data on the first call */
 4165                          4956         [ +  + ]:            321 :     if (state == NULL)
                               4957                 :             87 :         state = makeNumericAggState(fcinfo, true);
                               4958                 :                : 
                               4959         [ +  + ]:            321 :     if (!PG_ARGISNULL(1))
 4312                          4960                 :            312 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
                               4961                 :                : 
                               4962                 :            321 :     PG_RETURN_POINTER(state);
                               4963                 :                : }
                               4964                 :                : 
                               4965                 :                : /*
                               4966                 :                :  * Generic combine function for numeric aggregates which require sumX2
                               4967                 :                :  */
                               4968                 :                : Datum
 3441 rhaas@postgresql.org     4969                 :             18 : numeric_combine(PG_FUNCTION_ARGS)
                               4970                 :                : {
                               4971                 :                :     NumericAggState *state1;
                               4972                 :                :     NumericAggState *state2;
                               4973                 :                :     MemoryContext agg_context;
                               4974                 :                :     MemoryContext old_context;
                               4975                 :                : 
                               4976         [ -  + ]:             18 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3441 rhaas@postgresql.org     4977         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               4978                 :                : 
 3441 rhaas@postgresql.org     4979         [ +  + ]:CBC          18 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               4980         [ +  - ]:             18 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
                               4981                 :                : 
                               4982         [ -  + ]:             18 :     if (state2 == NULL)
 3441 rhaas@postgresql.org     4983                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               4984                 :                : 
                               4985                 :                :     /* manually copy all fields from state2 to state1 */
 3441 rhaas@postgresql.org     4986         [ +  + ]:CBC          18 :     if (state1 == NULL)
                               4987                 :                :     {
                               4988                 :              9 :         old_context = MemoryContextSwitchTo(agg_context);
                               4989                 :                : 
 3362 tgl@sss.pgh.pa.us        4990                 :              9 :         state1 = makeNumericAggStateCurrentContext(true);
 3441 rhaas@postgresql.org     4991                 :              9 :         state1->N = state2->N;
                               4992                 :              9 :         state1->NaNcount = state2->NaNcount;
 1872 tgl@sss.pgh.pa.us        4993                 :              9 :         state1->pInfcount = state2->pInfcount;
                               4994                 :              9 :         state1->nInfcount = state2->nInfcount;
 3441 rhaas@postgresql.org     4995                 :              9 :         state1->maxScale = state2->maxScale;
                               4996                 :              9 :         state1->maxScaleCount = state2->maxScaleCount;
                               4997                 :                : 
 3291 heikki.linnakangas@i     4998                 :              9 :         accum_sum_copy(&state1->sumX, &state2->sumX);
                               4999                 :              9 :         accum_sum_copy(&state1->sumX2, &state2->sumX2);
                               5000                 :                : 
 3441 rhaas@postgresql.org     5001                 :              9 :         MemoryContextSwitchTo(old_context);
                               5002                 :                : 
                               5003                 :              9 :         PG_RETURN_POINTER(state1);
                               5004                 :                :     }
                               5005                 :                : 
 1913 tgl@sss.pgh.pa.us        5006                 :              9 :     state1->N += state2->N;
                               5007                 :              9 :     state1->NaNcount += state2->NaNcount;
 1872                          5008                 :              9 :     state1->pInfcount += state2->pInfcount;
                               5009                 :              9 :     state1->nInfcount += state2->nInfcount;
                               5010                 :                : 
 3441 rhaas@postgresql.org     5011         [ +  - ]:              9 :     if (state2->N > 0)
                               5012                 :                :     {
                               5013                 :                :         /*
                               5014                 :                :          * These are currently only needed for moving aggregates, but let's do
                               5015                 :                :          * the right thing anyway...
                               5016                 :                :          */
                               5017         [ -  + ]:              9 :         if (state2->maxScale > state1->maxScale)
                               5018                 :                :         {
 3441 rhaas@postgresql.org     5019                 :UBC           0 :             state1->maxScale = state2->maxScale;
                               5020                 :              0 :             state1->maxScaleCount = state2->maxScaleCount;
                               5021                 :                :         }
 3441 rhaas@postgresql.org     5022         [ +  - ]:CBC           9 :         else if (state2->maxScale == state1->maxScale)
                               5023                 :              9 :             state1->maxScaleCount += state2->maxScaleCount;
                               5024                 :                : 
                               5025                 :                :         /* The rest of this needs to work in the aggregate context */
                               5026                 :              9 :         old_context = MemoryContextSwitchTo(agg_context);
                               5027                 :                : 
                               5028                 :                :         /* Accumulate sums */
 3291 heikki.linnakangas@i     5029                 :              9 :         accum_sum_combine(&state1->sumX, &state2->sumX);
                               5030                 :              9 :         accum_sum_combine(&state1->sumX2, &state2->sumX2);
                               5031                 :                : 
 3441 rhaas@postgresql.org     5032                 :              9 :         MemoryContextSwitchTo(old_context);
                               5033                 :                :     }
                               5034                 :              9 :     PG_RETURN_POINTER(state1);
                               5035                 :                : }
                               5036                 :                : 
                               5037                 :                : /*
                               5038                 :                :  * Generic transition function for numeric aggregates that don't require sumX2.
                               5039                 :                :  */
                               5040                 :                : Datum
 6776 bruce@momjian.us         5041                 :         936404 : numeric_avg_accum(PG_FUNCTION_ARGS)
                               5042                 :                : {
                               5043                 :                :     NumericAggState *state;
                               5044                 :                : 
 4312 tgl@sss.pgh.pa.us        5045         [ +  + ]:         936404 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5046                 :                : 
                               5047                 :                :     /* Create the state data on the first call */
 4165                          5048         [ +  + ]:         936404 :     if (state == NULL)
                               5049                 :          85453 :         state = makeNumericAggState(fcinfo, false);
                               5050                 :                : 
                               5051         [ +  + ]:         936404 :     if (!PG_ARGISNULL(1))
 4312                          5052                 :         936374 :         do_numeric_accum(state, PG_GETARG_NUMERIC(1));
                               5053                 :                : 
 4165                          5054                 :         936404 :     PG_RETURN_POINTER(state);
                               5055                 :                : }
                               5056                 :                : 
                               5057                 :                : /*
                               5058                 :                :  * Combine function for numeric aggregates which don't require sumX2
                               5059                 :                :  */
                               5060                 :                : Datum
 3441 rhaas@postgresql.org     5061                 :             12 : numeric_avg_combine(PG_FUNCTION_ARGS)
                               5062                 :                : {
                               5063                 :                :     NumericAggState *state1;
                               5064                 :                :     NumericAggState *state2;
                               5065                 :                :     MemoryContext agg_context;
                               5066                 :                :     MemoryContext old_context;
                               5067                 :                : 
                               5068         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3441 rhaas@postgresql.org     5069         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5070                 :                : 
 3441 rhaas@postgresql.org     5071         [ +  + ]:CBC          12 :     state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5072         [ +  - ]:             12 :     state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
                               5073                 :                : 
                               5074         [ -  + ]:             12 :     if (state2 == NULL)
 3441 rhaas@postgresql.org     5075                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5076                 :                : 
                               5077                 :                :     /* manually copy all fields from state2 to state1 */
 3441 rhaas@postgresql.org     5078         [ +  + ]:CBC          12 :     if (state1 == NULL)
                               5079                 :                :     {
                               5080                 :              3 :         old_context = MemoryContextSwitchTo(agg_context);
                               5081                 :                : 
 3362 tgl@sss.pgh.pa.us        5082                 :              3 :         state1 = makeNumericAggStateCurrentContext(false);
 3441 rhaas@postgresql.org     5083                 :              3 :         state1->N = state2->N;
                               5084                 :              3 :         state1->NaNcount = state2->NaNcount;
 1872 tgl@sss.pgh.pa.us        5085                 :              3 :         state1->pInfcount = state2->pInfcount;
                               5086                 :              3 :         state1->nInfcount = state2->nInfcount;
 3441 rhaas@postgresql.org     5087                 :              3 :         state1->maxScale = state2->maxScale;
                               5088                 :              3 :         state1->maxScaleCount = state2->maxScaleCount;
                               5089                 :                : 
 3291 heikki.linnakangas@i     5090                 :              3 :         accum_sum_copy(&state1->sumX, &state2->sumX);
                               5091                 :                : 
 3441 rhaas@postgresql.org     5092                 :              3 :         MemoryContextSwitchTo(old_context);
                               5093                 :                : 
                               5094                 :              3 :         PG_RETURN_POINTER(state1);
                               5095                 :                :     }
                               5096                 :                : 
 1913 tgl@sss.pgh.pa.us        5097                 :              9 :     state1->N += state2->N;
                               5098                 :              9 :     state1->NaNcount += state2->NaNcount;
 1872                          5099                 :              9 :     state1->pInfcount += state2->pInfcount;
                               5100                 :              9 :     state1->nInfcount += state2->nInfcount;
                               5101                 :                : 
 3441 rhaas@postgresql.org     5102         [ +  - ]:              9 :     if (state2->N > 0)
                               5103                 :                :     {
                               5104                 :                :         /*
                               5105                 :                :          * These are currently only needed for moving aggregates, but let's do
                               5106                 :                :          * the right thing anyway...
                               5107                 :                :          */
                               5108         [ -  + ]:              9 :         if (state2->maxScale > state1->maxScale)
                               5109                 :                :         {
 3441 rhaas@postgresql.org     5110                 :UBC           0 :             state1->maxScale = state2->maxScale;
                               5111                 :              0 :             state1->maxScaleCount = state2->maxScaleCount;
                               5112                 :                :         }
 3441 rhaas@postgresql.org     5113         [ +  - ]:CBC           9 :         else if (state2->maxScale == state1->maxScale)
                               5114                 :              9 :             state1->maxScaleCount += state2->maxScaleCount;
                               5115                 :                : 
                               5116                 :                :         /* The rest of this needs to work in the aggregate context */
                               5117                 :              9 :         old_context = MemoryContextSwitchTo(agg_context);
                               5118                 :                : 
                               5119                 :                :         /* Accumulate sums */
 3291 heikki.linnakangas@i     5120                 :              9 :         accum_sum_combine(&state1->sumX, &state2->sumX);
                               5121                 :                : 
 3441 rhaas@postgresql.org     5122                 :              9 :         MemoryContextSwitchTo(old_context);
                               5123                 :                :     }
                               5124                 :              9 :     PG_RETURN_POINTER(state1);
                               5125                 :                : }
                               5126                 :                : 
                               5127                 :                : /*
                               5128                 :                :  * numeric_avg_serialize
                               5129                 :                :  *      Serialize NumericAggState for numeric aggregates that don't require
                               5130                 :                :  *      sumX2.
                               5131                 :                :  */
                               5132                 :                : Datum
                               5133                 :             12 : numeric_avg_serialize(PG_FUNCTION_ARGS)
                               5134                 :                : {
                               5135                 :                :     NumericAggState *state;
                               5136                 :                :     StringInfoData buf;
                               5137                 :                :     bytea      *result;
                               5138                 :                :     NumericVar  tmp_var;
                               5139                 :                : 
                               5140                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5141         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5142         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5143                 :                : 
 3441 rhaas@postgresql.org     5144                 :CBC          12 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
                               5145                 :                : 
 3291 heikki.linnakangas@i     5146                 :             12 :     init_var(&tmp_var);
                               5147                 :                : 
 3441 rhaas@postgresql.org     5148                 :             12 :     pq_begintypsend(&buf);
                               5149                 :                : 
                               5150                 :                :     /* N */
                               5151                 :             12 :     pq_sendint64(&buf, state->N);
                               5152                 :                : 
                               5153                 :                :     /* sumX */
 1524 dean.a.rasheed@gmail     5154                 :             12 :     accum_sum_final(&state->sumX, &tmp_var);
                               5155                 :             12 :     numericvar_serialize(&buf, &tmp_var);
                               5156                 :                : 
                               5157                 :                :     /* maxScale */
 2887 andres@anarazel.de       5158                 :             12 :     pq_sendint32(&buf, state->maxScale);
                               5159                 :                : 
                               5160                 :                :     /* maxScaleCount */
 3441 rhaas@postgresql.org     5161                 :             12 :     pq_sendint64(&buf, state->maxScaleCount);
                               5162                 :                : 
                               5163                 :                :     /* NaNcount */
                               5164                 :             12 :     pq_sendint64(&buf, state->NaNcount);
                               5165                 :                : 
                               5166                 :                :     /* pInfcount */
 1872 tgl@sss.pgh.pa.us        5167                 :             12 :     pq_sendint64(&buf, state->pInfcount);
                               5168                 :                : 
                               5169                 :                :     /* nInfcount */
                               5170                 :             12 :     pq_sendint64(&buf, state->nInfcount);
                               5171                 :                : 
 3441 rhaas@postgresql.org     5172                 :             12 :     result = pq_endtypsend(&buf);
                               5173                 :                : 
 1524 dean.a.rasheed@gmail     5174                 :             12 :     free_var(&tmp_var);
                               5175                 :                : 
 3441 rhaas@postgresql.org     5176                 :             12 :     PG_RETURN_BYTEA_P(result);
                               5177                 :                : }
                               5178                 :                : 
                               5179                 :                : /*
                               5180                 :                :  * numeric_avg_deserialize
                               5181                 :                :  *      Deserialize bytea into NumericAggState for numeric aggregates that
                               5182                 :                :  *      don't require sumX2.
                               5183                 :                :  */
                               5184                 :                : Datum
                               5185                 :             12 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
                               5186                 :                : {
                               5187                 :                :     bytea      *sstate;
                               5188                 :                :     NumericAggState *result;
                               5189                 :                :     StringInfoData buf;
                               5190                 :                :     NumericVar  tmp_var;
                               5191                 :                : 
                               5192         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5193         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5194                 :                : 
 3100 noah@leadboat.com        5195                 :CBC          12 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5196                 :                : 
 1524 dean.a.rasheed@gmail     5197                 :             12 :     init_var(&tmp_var);
                               5198                 :                : 
                               5199                 :                :     /*
                               5200                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5201                 :                :      * recv-function infrastructure.
                               5202                 :                :      */
  680 drowley@postgresql.o     5203         [ +  - ]:             12 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5204   [ -  +  -  -  :             12 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 - ]
                               5205                 :                : 
 3362 tgl@sss.pgh.pa.us        5206                 :             12 :     result = makeNumericAggStateCurrentContext(false);
                               5207                 :                : 
                               5208                 :                :     /* N */
 3441 rhaas@postgresql.org     5209                 :             12 :     result->N = pq_getmsgint64(&buf);
                               5210                 :                : 
                               5211                 :                :     /* sumX */
 1524 dean.a.rasheed@gmail     5212                 :             12 :     numericvar_deserialize(&buf, &tmp_var);
 3291 heikki.linnakangas@i     5213                 :             12 :     accum_sum_add(&(result->sumX), &tmp_var);
                               5214                 :                : 
                               5215                 :                :     /* maxScale */
 3441 rhaas@postgresql.org     5216                 :             12 :     result->maxScale = pq_getmsgint(&buf, 4);
                               5217                 :                : 
                               5218                 :                :     /* maxScaleCount */
                               5219                 :             12 :     result->maxScaleCount = pq_getmsgint64(&buf);
                               5220                 :                : 
                               5221                 :                :     /* NaNcount */
                               5222                 :             12 :     result->NaNcount = pq_getmsgint64(&buf);
                               5223                 :                : 
                               5224                 :                :     /* pInfcount */
 1872 tgl@sss.pgh.pa.us        5225                 :             12 :     result->pInfcount = pq_getmsgint64(&buf);
                               5226                 :                : 
                               5227                 :                :     /* nInfcount */
                               5228                 :             12 :     result->nInfcount = pq_getmsgint64(&buf);
                               5229                 :                : 
 3441 rhaas@postgresql.org     5230                 :             12 :     pq_getmsgend(&buf);
                               5231                 :                : 
 1524 dean.a.rasheed@gmail     5232                 :             12 :     free_var(&tmp_var);
                               5233                 :                : 
 3441 rhaas@postgresql.org     5234                 :             12 :     PG_RETURN_POINTER(result);
                               5235                 :                : }
                               5236                 :                : 
                               5237                 :                : /*
                               5238                 :                :  * numeric_serialize
                               5239                 :                :  *      Serialization function for NumericAggState for numeric aggregates that
                               5240                 :                :  *      require sumX2.
                               5241                 :                :  */
                               5242                 :                : Datum
                               5243                 :             18 : numeric_serialize(PG_FUNCTION_ARGS)
                               5244                 :                : {
                               5245                 :                :     NumericAggState *state;
                               5246                 :                :     StringInfoData buf;
                               5247                 :                :     bytea      *result;
                               5248                 :                :     NumericVar  tmp_var;
                               5249                 :                : 
                               5250                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5251         [ -  + ]:             18 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5252         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5253                 :                : 
 3441 rhaas@postgresql.org     5254                 :CBC          18 :     state = (NumericAggState *) PG_GETARG_POINTER(0);
                               5255                 :                : 
 3291 heikki.linnakangas@i     5256                 :             18 :     init_var(&tmp_var);
                               5257                 :                : 
 3441 rhaas@postgresql.org     5258                 :             18 :     pq_begintypsend(&buf);
                               5259                 :                : 
                               5260                 :                :     /* N */
                               5261                 :             18 :     pq_sendint64(&buf, state->N);
                               5262                 :                : 
                               5263                 :                :     /* sumX */
 1524 dean.a.rasheed@gmail     5264                 :             18 :     accum_sum_final(&state->sumX, &tmp_var);
                               5265                 :             18 :     numericvar_serialize(&buf, &tmp_var);
                               5266                 :                : 
                               5267                 :                :     /* sumX2 */
                               5268                 :             18 :     accum_sum_final(&state->sumX2, &tmp_var);
                               5269                 :             18 :     numericvar_serialize(&buf, &tmp_var);
                               5270                 :                : 
                               5271                 :                :     /* maxScale */
 2887 andres@anarazel.de       5272                 :             18 :     pq_sendint32(&buf, state->maxScale);
                               5273                 :                : 
                               5274                 :                :     /* maxScaleCount */
 3441 rhaas@postgresql.org     5275                 :             18 :     pq_sendint64(&buf, state->maxScaleCount);
                               5276                 :                : 
                               5277                 :                :     /* NaNcount */
                               5278                 :             18 :     pq_sendint64(&buf, state->NaNcount);
                               5279                 :                : 
                               5280                 :                :     /* pInfcount */
 1872 tgl@sss.pgh.pa.us        5281                 :             18 :     pq_sendint64(&buf, state->pInfcount);
                               5282                 :                : 
                               5283                 :                :     /* nInfcount */
                               5284                 :             18 :     pq_sendint64(&buf, state->nInfcount);
                               5285                 :                : 
 3441 rhaas@postgresql.org     5286                 :             18 :     result = pq_endtypsend(&buf);
                               5287                 :                : 
 1524 dean.a.rasheed@gmail     5288                 :             18 :     free_var(&tmp_var);
                               5289                 :                : 
 3441 rhaas@postgresql.org     5290                 :             18 :     PG_RETURN_BYTEA_P(result);
                               5291                 :                : }
                               5292                 :                : 
                               5293                 :                : /*
                               5294                 :                :  * numeric_deserialize
                               5295                 :                :  *      Deserialization function for NumericAggState for numeric aggregates that
                               5296                 :                :  *      require sumX2.
                               5297                 :                :  */
                               5298                 :                : Datum
                               5299                 :             18 : numeric_deserialize(PG_FUNCTION_ARGS)
                               5300                 :                : {
                               5301                 :                :     bytea      *sstate;
                               5302                 :                :     NumericAggState *result;
                               5303                 :                :     StringInfoData buf;
                               5304                 :                :     NumericVar  tmp_var;
                               5305                 :                : 
                               5306         [ -  + ]:             18 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5307         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5308                 :                : 
 3100 noah@leadboat.com        5309                 :CBC          18 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5310                 :                : 
 1524 dean.a.rasheed@gmail     5311                 :             18 :     init_var(&tmp_var);
                               5312                 :                : 
                               5313                 :                :     /*
                               5314                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5315                 :                :      * recv-function infrastructure.
                               5316                 :                :      */
  680 drowley@postgresql.o     5317         [ +  + ]:             18 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5318   [ -  +  -  -  :             18 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 + ]
                               5319                 :                : 
 3362 tgl@sss.pgh.pa.us        5320                 :             18 :     result = makeNumericAggStateCurrentContext(false);
                               5321                 :                : 
                               5322                 :                :     /* N */
 3441 rhaas@postgresql.org     5323                 :             18 :     result->N = pq_getmsgint64(&buf);
                               5324                 :                : 
                               5325                 :                :     /* sumX */
 1524 dean.a.rasheed@gmail     5326                 :             18 :     numericvar_deserialize(&buf, &tmp_var);
                               5327                 :             18 :     accum_sum_add(&(result->sumX), &tmp_var);
                               5328                 :                : 
                               5329                 :                :     /* sumX2 */
                               5330                 :             18 :     numericvar_deserialize(&buf, &tmp_var);
                               5331                 :             18 :     accum_sum_add(&(result->sumX2), &tmp_var);
                               5332                 :                : 
                               5333                 :                :     /* maxScale */
 3441 rhaas@postgresql.org     5334                 :             18 :     result->maxScale = pq_getmsgint(&buf, 4);
                               5335                 :                : 
                               5336                 :                :     /* maxScaleCount */
                               5337                 :             18 :     result->maxScaleCount = pq_getmsgint64(&buf);
                               5338                 :                : 
                               5339                 :                :     /* NaNcount */
                               5340                 :             18 :     result->NaNcount = pq_getmsgint64(&buf);
                               5341                 :                : 
                               5342                 :                :     /* pInfcount */
 1872 tgl@sss.pgh.pa.us        5343                 :             18 :     result->pInfcount = pq_getmsgint64(&buf);
                               5344                 :                : 
                               5345                 :                :     /* nInfcount */
                               5346                 :             18 :     result->nInfcount = pq_getmsgint64(&buf);
                               5347                 :                : 
 3441 rhaas@postgresql.org     5348                 :             18 :     pq_getmsgend(&buf);
                               5349                 :                : 
 1524 dean.a.rasheed@gmail     5350                 :             18 :     free_var(&tmp_var);
                               5351                 :                : 
 3441 rhaas@postgresql.org     5352                 :             18 :     PG_RETURN_POINTER(result);
                               5353                 :                : }
                               5354                 :                : 
                               5355                 :                : /*
                               5356                 :                :  * Generic inverse transition function for numeric aggregates
                               5357                 :                :  * (with or without requirement for X^2).
                               5358                 :                :  */
                               5359                 :                : Datum
 4165 tgl@sss.pgh.pa.us        5360                 :            114 : numeric_accum_inv(PG_FUNCTION_ARGS)
                               5361                 :                : {
                               5362                 :                :     NumericAggState *state;
                               5363                 :                : 
                               5364         [ +  - ]:            114 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5365                 :                : 
                               5366                 :                :     /* Should not get here with no state */
                               5367         [ -  + ]:            114 :     if (state == NULL)
 4165 tgl@sss.pgh.pa.us        5368         [ #  # ]:UBC           0 :         elog(ERROR, "numeric_accum_inv called with NULL state");
                               5369                 :                : 
 4165 tgl@sss.pgh.pa.us        5370         [ +  + ]:CBC         114 :     if (!PG_ARGISNULL(1))
                               5371                 :                :     {
                               5372                 :                :         /* If we fail to perform the inverse transition, return NULL */
                               5373         [ +  + ]:             99 :         if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
                               5374                 :              3 :             PG_RETURN_NULL();
                               5375                 :                :     }
                               5376                 :                : 
 4312                          5377                 :            111 :     PG_RETURN_POINTER(state);
                               5378                 :                : }
                               5379                 :                : 
                               5380                 :                : 
                               5381                 :                : /*
                               5382                 :                :  * Integer data types in general use Numeric accumulators to share code and
                               5383                 :                :  * avoid risk of overflow.  However for performance reasons optimized
                               5384                 :                :  * special-purpose accumulator routines are used when possible:
                               5385                 :                :  *
                               5386                 :                :  * For 16-bit and 32-bit inputs, N and sum(X) fit into 64-bit, so 64-bit
                               5387                 :                :  * accumulators are used for SUM and AVG of these data types.
                               5388                 :                :  *
                               5389                 :                :  * For 16-bit and 32-bit inputs, sum(X^2) fits into 128-bit, so 128-bit
                               5390                 :                :  * accumulators are used for STDDEV_POP, STDDEV_SAMP, VAR_POP, and VAR_SAMP of
                               5391                 :                :  * these data types.
                               5392                 :                :  *
                               5393                 :                :  * For 64-bit inputs, sum(X) fits into 128-bit, so a 128-bit accumulator is
                               5394                 :                :  * used for SUM(int8) and AVG(int8).
                               5395                 :                :  */
                               5396                 :                : 
                               5397                 :                : typedef struct Int128AggState
                               5398                 :                : {
                               5399                 :                :     bool        calcSumX2;      /* if true, calculate sumX2 */
                               5400                 :                :     int64       N;              /* count of processed numbers */
                               5401                 :                :     INT128      sumX;           /* sum of processed numbers */
                               5402                 :                :     INT128      sumX2;          /* sum of squares of processed numbers */
                               5403                 :                : } Int128AggState;
                               5404                 :                : 
                               5405                 :                : /*
                               5406                 :                :  * Prepare state data for a 128-bit aggregate function that needs to compute
                               5407                 :                :  * sum, count and optionally sum of squares of the input.
                               5408                 :                :  */
                               5409                 :                : static Int128AggState *
 3823 andres@anarazel.de       5410                 :            484 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
                               5411                 :                : {
                               5412                 :                :     Int128AggState *state;
                               5413                 :                :     MemoryContext agg_context;
                               5414                 :                :     MemoryContext old_context;
                               5415                 :                : 
                               5416         [ -  + ]:            484 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3823 andres@anarazel.de       5417         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5418                 :                : 
 3823 andres@anarazel.de       5419                 :CBC         484 :     old_context = MemoryContextSwitchTo(agg_context);
                               5420                 :                : 
                               5421                 :            484 :     state = (Int128AggState *) palloc0(sizeof(Int128AggState));
                               5422                 :            484 :     state->calcSumX2 = calcSumX2;
                               5423                 :                : 
                               5424                 :            484 :     MemoryContextSwitchTo(old_context);
                               5425                 :                : 
                               5426                 :            484 :     return state;
                               5427                 :                : }
                               5428                 :                : 
                               5429                 :                : /*
                               5430                 :                :  * Like makeInt128AggState(), but allocate the state in the current memory
                               5431                 :                :  * context.
                               5432                 :                :  */
                               5433                 :                : static Int128AggState *
 3362 tgl@sss.pgh.pa.us        5434                 :             27 : makeInt128AggStateCurrentContext(bool calcSumX2)
                               5435                 :                : {
                               5436                 :                :     Int128AggState *state;
                               5437                 :                : 
                               5438                 :             27 :     state = (Int128AggState *) palloc0(sizeof(Int128AggState));
                               5439                 :             27 :     state->calcSumX2 = calcSumX2;
                               5440                 :                : 
                               5441                 :             27 :     return state;
                               5442                 :                : }
                               5443                 :                : 
                               5444                 :                : /*
                               5445                 :                :  * Accumulate a new input value for 128-bit aggregate functions.
                               5446                 :                :  */
                               5447                 :                : static void
   30 dean.a.rasheed@gmail     5448                 :GNC      278739 : do_int128_accum(Int128AggState *state, int64 newval)
                               5449                 :                : {
 3823 andres@anarazel.de       5450         [ +  + ]:CBC      278739 :     if (state->calcSumX2)
   30 dean.a.rasheed@gmail     5451                 :GNC      121180 :         int128_add_int64_mul_int64(&state->sumX2, newval, newval);
                               5452                 :                : 
                               5453                 :         278739 :     int128_add_int64(&state->sumX, newval);
 3823 andres@anarazel.de       5454                 :CBC      278739 :     state->N++;
                               5455                 :         278739 : }
                               5456                 :                : 
                               5457                 :                : /*
                               5458                 :                :  * Remove an input value from the aggregated state.
                               5459                 :                :  */
                               5460                 :                : static void
   30 dean.a.rasheed@gmail     5461                 :GNC         156 : do_int128_discard(Int128AggState *state, int64 newval)
                               5462                 :                : {
 3823 andres@anarazel.de       5463         [ +  + ]:CBC         156 :     if (state->calcSumX2)
   30 dean.a.rasheed@gmail     5464                 :GNC         144 :         int128_sub_int64_mul_int64(&state->sumX2, newval, newval);
                               5465                 :                : 
                               5466                 :            156 :     int128_sub_int64(&state->sumX, newval);
 3823 andres@anarazel.de       5467                 :CBC         156 :     state->N--;
                               5468                 :            156 : }
                               5469                 :                : 
                               5470                 :                : Datum
 9182 tgl@sss.pgh.pa.us        5471                 :             99 : int2_accum(PG_FUNCTION_ARGS)
                               5472                 :                : {
                               5473                 :                :     Int128AggState *state;
                               5474                 :                : 
   30 dean.a.rasheed@gmail     5475         [ +  + ]:GNC          99 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5476                 :                : 
                               5477                 :                :     /* Create the state data on the first call */
 4165 tgl@sss.pgh.pa.us        5478         [ +  + ]:CBC          99 :     if (state == NULL)
   30 dean.a.rasheed@gmail     5479                 :GNC          18 :         state = makeInt128AggState(fcinfo, true);
                               5480                 :                : 
 4312 tgl@sss.pgh.pa.us        5481         [ +  + ]:CBC          99 :     if (!PG_ARGISNULL(1))
   30 dean.a.rasheed@gmail     5482                 :GNC          90 :         do_int128_accum(state, PG_GETARG_INT16(1));
                               5483                 :                : 
 4312 tgl@sss.pgh.pa.us        5484                 :CBC          99 :     PG_RETURN_POINTER(state);
                               5485                 :                : }
                               5486                 :                : 
                               5487                 :                : Datum
 9182                          5488                 :         121099 : int4_accum(PG_FUNCTION_ARGS)
                               5489                 :                : {
                               5490                 :                :     Int128AggState *state;
                               5491                 :                : 
   30 dean.a.rasheed@gmail     5492         [ +  + ]:GNC      121099 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5493                 :                : 
                               5494                 :                :     /* Create the state data on the first call */
 4165 tgl@sss.pgh.pa.us        5495         [ +  + ]:CBC      121099 :     if (state == NULL)
   30 dean.a.rasheed@gmail     5496                 :GNC          40 :         state = makeInt128AggState(fcinfo, true);
                               5497                 :                : 
 4312 tgl@sss.pgh.pa.us        5498         [ +  + ]:CBC      121099 :     if (!PG_ARGISNULL(1))
   30 dean.a.rasheed@gmail     5499                 :GNC      121090 :         do_int128_accum(state, PG_GETARG_INT32(1));
                               5500                 :                : 
 4312 tgl@sss.pgh.pa.us        5501                 :CBC      121099 :     PG_RETURN_POINTER(state);
                               5502                 :                : }
                               5503                 :                : 
                               5504                 :                : Datum
 9182                          5505                 :         120099 : int8_accum(PG_FUNCTION_ARGS)
                               5506                 :                : {
                               5507                 :                :     NumericAggState *state;
                               5508                 :                : 
 4312                          5509         [ +  + ]:         120099 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5510                 :                : 
                               5511                 :                :     /* Create the state data on the first call */
 4165                          5512         [ +  + ]:         120099 :     if (state == NULL)
                               5513                 :             30 :         state = makeNumericAggState(fcinfo, true);
                               5514                 :                : 
 4312                          5515         [ +  + ]:         120099 :     if (!PG_ARGISNULL(1))
 1823 peter@eisentraut.org     5516                 :         120090 :         do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
                               5517                 :                : 
 4312 tgl@sss.pgh.pa.us        5518                 :         120099 :     PG_RETURN_POINTER(state);
                               5519                 :                : }
                               5520                 :                : 
                               5521                 :                : /*
                               5522                 :                :  * Combine function for Int128AggState for aggregates which require sumX2
                               5523                 :                :  */
                               5524                 :                : Datum
 3441 rhaas@postgresql.org     5525                 :             12 : numeric_poly_combine(PG_FUNCTION_ARGS)
                               5526                 :                : {
                               5527                 :                :     Int128AggState *state1;
                               5528                 :                :     Int128AggState *state2;
                               5529                 :                :     MemoryContext agg_context;
                               5530                 :                :     MemoryContext old_context;
                               5531                 :                : 
                               5532         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3441 rhaas@postgresql.org     5533         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5534                 :                : 
   30 dean.a.rasheed@gmail     5535         [ +  + ]:GNC          12 :     state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5536         [ +  - ]:             12 :     state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
                               5537                 :                : 
 3441 rhaas@postgresql.org     5538         [ -  + ]:CBC          12 :     if (state2 == NULL)
 3441 rhaas@postgresql.org     5539                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5540                 :                : 
                               5541                 :                :     /* manually copy all fields from state2 to state1 */
 3441 rhaas@postgresql.org     5542         [ +  + ]:CBC          12 :     if (state1 == NULL)
                               5543                 :                :     {
                               5544                 :              3 :         old_context = MemoryContextSwitchTo(agg_context);
                               5545                 :                : 
   30 dean.a.rasheed@gmail     5546                 :GNC           3 :         state1 = makeInt128AggState(fcinfo, true);
 3441 rhaas@postgresql.org     5547                 :CBC           3 :         state1->N = state2->N;
                               5548                 :              3 :         state1->sumX = state2->sumX;
                               5549                 :              3 :         state1->sumX2 = state2->sumX2;
                               5550                 :                : 
                               5551                 :              3 :         MemoryContextSwitchTo(old_context);
                               5552                 :                : 
                               5553                 :              3 :         PG_RETURN_POINTER(state1);
                               5554                 :                :     }
                               5555                 :                : 
                               5556         [ +  - ]:              9 :     if (state2->N > 0)
                               5557                 :                :     {
                               5558                 :              9 :         state1->N += state2->N;
   30 dean.a.rasheed@gmail     5559                 :GNC           9 :         int128_add_int128(&state1->sumX, state2->sumX);
                               5560                 :              9 :         int128_add_int128(&state1->sumX2, state2->sumX2);
                               5561                 :                :     }
                               5562                 :              9 :     PG_RETURN_POINTER(state1);
                               5563                 :                : }
                               5564                 :                : 
                               5565                 :                : /*
                               5566                 :                :  * int128_serialize - serialize a 128-bit integer to binary format
                               5567                 :                :  */
                               5568                 :                : static inline void
                               5569                 :             39 : int128_serialize(StringInfo buf, INT128 val)
                               5570                 :                : {
                               5571                 :             39 :     pq_sendint64(buf, PG_INT128_HI_INT64(val));
                               5572                 :             39 :     pq_sendint64(buf, PG_INT128_LO_UINT64(val));
                               5573                 :             39 : }
                               5574                 :                : 
                               5575                 :                : /*
                               5576                 :                :  * int128_deserialize - deserialize binary format to a 128-bit integer.
                               5577                 :                :  */
                               5578                 :                : static inline INT128
                               5579                 :             39 : int128_deserialize(StringInfo buf)
                               5580                 :                : {
                               5581                 :             39 :     int64       hi = pq_getmsgint64(buf);
                               5582                 :             39 :     uint64      lo = pq_getmsgint64(buf);
                               5583                 :                : 
                               5584                 :             39 :     return make_int128(hi, lo);
                               5585                 :                : }
                               5586                 :                : 
                               5587                 :                : /*
                               5588                 :                :  * numeric_poly_serialize
                               5589                 :                :  *      Serialize Int128AggState into bytea for aggregate functions which
                               5590                 :                :  *      require sumX2.
                               5591                 :                :  */
                               5592                 :                : Datum
 3441 rhaas@postgresql.org     5593                 :CBC          12 : numeric_poly_serialize(PG_FUNCTION_ARGS)
                               5594                 :                : {
                               5595                 :                :     Int128AggState *state;
                               5596                 :                :     StringInfoData buf;
                               5597                 :                :     bytea      *result;
                               5598                 :                : 
                               5599                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5600         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5601         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5602                 :                : 
   30 dean.a.rasheed@gmail     5603                 :GNC          12 :     state = (Int128AggState *) PG_GETARG_POINTER(0);
                               5604                 :                : 
 3441 rhaas@postgresql.org     5605                 :CBC          12 :     pq_begintypsend(&buf);
                               5606                 :                : 
                               5607                 :                :     /* N */
                               5608                 :             12 :     pq_sendint64(&buf, state->N);
                               5609                 :                : 
                               5610                 :                :     /* sumX */
   30 dean.a.rasheed@gmail     5611                 :GNC          12 :     int128_serialize(&buf, state->sumX);
                               5612                 :                : 
                               5613                 :                :     /* sumX2 */
                               5614                 :             12 :     int128_serialize(&buf, state->sumX2);
                               5615                 :                : 
 3441 rhaas@postgresql.org     5616                 :CBC          12 :     result = pq_endtypsend(&buf);
                               5617                 :                : 
                               5618                 :             12 :     PG_RETURN_BYTEA_P(result);
                               5619                 :                : }
                               5620                 :                : 
                               5621                 :                : /*
                               5622                 :                :  * numeric_poly_deserialize
                               5623                 :                :  *      Deserialize Int128AggState from bytea for aggregate functions which
                               5624                 :                :  *      require sumX2.
                               5625                 :                :  */
                               5626                 :                : Datum
                               5627                 :             12 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
                               5628                 :                : {
                               5629                 :                :     bytea      *sstate;
                               5630                 :                :     Int128AggState *result;
                               5631                 :                :     StringInfoData buf;
                               5632                 :                : 
                               5633         [ -  + ]:             12 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5634         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5635                 :                : 
 3100 noah@leadboat.com        5636                 :CBC          12 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5637                 :                : 
                               5638                 :                :     /*
                               5639                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5640                 :                :      * recv-function infrastructure.
                               5641                 :                :      */
  680 drowley@postgresql.o     5642         [ +  - ]:             12 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5643   [ -  +  -  -  :             12 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 - ]
                               5644                 :                : 
   30 dean.a.rasheed@gmail     5645                 :GNC          12 :     result = makeInt128AggStateCurrentContext(false);
                               5646                 :                : 
                               5647                 :                :     /* N */
 3441 rhaas@postgresql.org     5648                 :CBC          12 :     result->N = pq_getmsgint64(&buf);
                               5649                 :                : 
                               5650                 :                :     /* sumX */
   30 dean.a.rasheed@gmail     5651                 :GNC          12 :     result->sumX = int128_deserialize(&buf);
                               5652                 :                : 
                               5653                 :                :     /* sumX2 */
                               5654                 :             12 :     result->sumX2 = int128_deserialize(&buf);
                               5655                 :                : 
 3441 rhaas@postgresql.org     5656                 :CBC          12 :     pq_getmsgend(&buf);
                               5657                 :                : 
                               5658                 :             12 :     PG_RETURN_POINTER(result);
                               5659                 :                : }
                               5660                 :                : 
                               5661                 :                : /*
                               5662                 :                :  * Transition function for int8 input when we don't need sumX2.
                               5663                 :                :  */
                               5664                 :                : Datum
 6776 bruce@momjian.us         5665                 :         159458 : int8_avg_accum(PG_FUNCTION_ARGS)
                               5666                 :                : {
                               5667                 :                :     Int128AggState *state;
                               5668                 :                : 
   30 dean.a.rasheed@gmail     5669         [ +  + ]:GNC      159458 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5670                 :                : 
                               5671                 :                :     /* Create the state data on the first call */
 4165 tgl@sss.pgh.pa.us        5672         [ +  + ]:CBC      159458 :     if (state == NULL)
   30 dean.a.rasheed@gmail     5673                 :GNC         417 :         state = makeInt128AggState(fcinfo, false);
                               5674                 :                : 
 4312 tgl@sss.pgh.pa.us        5675         [ +  + ]:CBC      159458 :     if (!PG_ARGISNULL(1))
   30 dean.a.rasheed@gmail     5676                 :GNC      157559 :         do_int128_accum(state, PG_GETARG_INT64(1));
                               5677                 :                : 
 4165 tgl@sss.pgh.pa.us        5678                 :CBC      159458 :     PG_RETURN_POINTER(state);
                               5679                 :                : }
                               5680                 :                : 
                               5681                 :                : /*
                               5682                 :                :  * Combine function for Int128AggState for aggregates which don't require
                               5683                 :                :  * sumX2
                               5684                 :                :  */
                               5685                 :                : Datum
 3441 rhaas@postgresql.org     5686                 :             15 : int8_avg_combine(PG_FUNCTION_ARGS)
                               5687                 :                : {
                               5688                 :                :     Int128AggState *state1;
                               5689                 :                :     Int128AggState *state2;
                               5690                 :                :     MemoryContext agg_context;
                               5691                 :                :     MemoryContext old_context;
                               5692                 :                : 
                               5693         [ -  + ]:             15 :     if (!AggCheckCallContext(fcinfo, &agg_context))
 3441 rhaas@postgresql.org     5694         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5695                 :                : 
   30 dean.a.rasheed@gmail     5696         [ +  + ]:GNC          15 :     state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5697         [ +  - ]:             15 :     state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
                               5698                 :                : 
 3441 rhaas@postgresql.org     5699         [ -  + ]:CBC          15 :     if (state2 == NULL)
 3441 rhaas@postgresql.org     5700                 :UBC           0 :         PG_RETURN_POINTER(state1);
                               5701                 :                : 
                               5702                 :                :     /* manually copy all fields from state2 to state1 */
 3441 rhaas@postgresql.org     5703         [ +  + ]:CBC          15 :     if (state1 == NULL)
                               5704                 :                :     {
                               5705                 :              6 :         old_context = MemoryContextSwitchTo(agg_context);
                               5706                 :                : 
   30 dean.a.rasheed@gmail     5707                 :GNC           6 :         state1 = makeInt128AggState(fcinfo, false);
 3441 rhaas@postgresql.org     5708                 :CBC           6 :         state1->N = state2->N;
                               5709                 :              6 :         state1->sumX = state2->sumX;
                               5710                 :                : 
                               5711                 :              6 :         MemoryContextSwitchTo(old_context);
                               5712                 :                : 
                               5713                 :              6 :         PG_RETURN_POINTER(state1);
                               5714                 :                :     }
                               5715                 :                : 
                               5716         [ +  - ]:              9 :     if (state2->N > 0)
                               5717                 :                :     {
                               5718                 :              9 :         state1->N += state2->N;
   30 dean.a.rasheed@gmail     5719                 :GNC           9 :         int128_add_int128(&state1->sumX, state2->sumX);
                               5720                 :                :     }
 3441 rhaas@postgresql.org     5721                 :CBC           9 :     PG_RETURN_POINTER(state1);
                               5722                 :                : }
                               5723                 :                : 
                               5724                 :                : /*
                               5725                 :                :  * int8_avg_serialize
                               5726                 :                :  *      Serialize Int128AggState into bytea for aggregate functions which
                               5727                 :                :  *      don't require sumX2.
                               5728                 :                :  */
                               5729                 :                : Datum
                               5730                 :             15 : int8_avg_serialize(PG_FUNCTION_ARGS)
                               5731                 :                : {
                               5732                 :                :     Int128AggState *state;
                               5733                 :                :     StringInfoData buf;
                               5734                 :                :     bytea      *result;
                               5735                 :                : 
                               5736                 :                :     /* Ensure we disallow calling when not in aggregate context */
                               5737         [ -  + ]:             15 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5738         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5739                 :                : 
   30 dean.a.rasheed@gmail     5740                 :GNC          15 :     state = (Int128AggState *) PG_GETARG_POINTER(0);
                               5741                 :                : 
 3441 rhaas@postgresql.org     5742                 :CBC          15 :     pq_begintypsend(&buf);
                               5743                 :                : 
                               5744                 :                :     /* N */
                               5745                 :             15 :     pq_sendint64(&buf, state->N);
                               5746                 :                : 
                               5747                 :                :     /* sumX */
   30 dean.a.rasheed@gmail     5748                 :GNC          15 :     int128_serialize(&buf, state->sumX);
                               5749                 :                : 
 3441 rhaas@postgresql.org     5750                 :CBC          15 :     result = pq_endtypsend(&buf);
                               5751                 :                : 
                               5752                 :             15 :     PG_RETURN_BYTEA_P(result);
                               5753                 :                : }
                               5754                 :                : 
                               5755                 :                : /*
                               5756                 :                :  * int8_avg_deserialize
                               5757                 :                :  *      Deserialize Int128AggState from bytea for aggregate functions which
                               5758                 :                :  *      don't require sumX2.
                               5759                 :                :  */
                               5760                 :                : Datum
                               5761                 :             15 : int8_avg_deserialize(PG_FUNCTION_ARGS)
                               5762                 :                : {
                               5763                 :                :     bytea      *sstate;
                               5764                 :                :     Int128AggState *result;
                               5765                 :                :     StringInfoData buf;
                               5766                 :                : 
                               5767         [ -  + ]:             15 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     5768         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               5769                 :                : 
 3100 noah@leadboat.com        5770                 :CBC          15 :     sstate = PG_GETARG_BYTEA_PP(0);
                               5771                 :                : 
                               5772                 :                :     /*
                               5773                 :                :      * Initialize a StringInfo so that we can "receive" it using the standard
                               5774                 :                :      * recv-function infrastructure.
                               5775                 :                :      */
  680 drowley@postgresql.o     5776         [ +  - ]:             15 :     initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
                               5777   [ -  +  -  -  :             15 :                            VARSIZE_ANY_EXHDR(sstate));
                                     -  -  -  -  +  
                                                 - ]
                               5778                 :                : 
   30 dean.a.rasheed@gmail     5779                 :GNC          15 :     result = makeInt128AggStateCurrentContext(false);
                               5780                 :                : 
                               5781                 :                :     /* N */
 3441 rhaas@postgresql.org     5782                 :CBC          15 :     result->N = pq_getmsgint64(&buf);
                               5783                 :                : 
                               5784                 :                :     /* sumX */
   30 dean.a.rasheed@gmail     5785                 :GNC          15 :     result->sumX = int128_deserialize(&buf);
                               5786                 :                : 
 3441 rhaas@postgresql.org     5787                 :CBC          15 :     pq_getmsgend(&buf);
                               5788                 :                : 
                               5789                 :             15 :     PG_RETURN_POINTER(result);
                               5790                 :                : }
                               5791                 :                : 
                               5792                 :                : /*
                               5793                 :                :  * Inverse transition functions to go with the above.
                               5794                 :                :  */
                               5795                 :                : 
                               5796                 :                : Datum
 4165 tgl@sss.pgh.pa.us        5797                 :             81 : int2_accum_inv(PG_FUNCTION_ARGS)
                               5798                 :                : {
                               5799                 :                :     Int128AggState *state;
                               5800                 :                : 
   30 dean.a.rasheed@gmail     5801         [ +  - ]:GNC          81 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5802                 :                : 
                               5803                 :                :     /* Should not get here with no state */
 4165 tgl@sss.pgh.pa.us        5804         [ -  + ]:CBC          81 :     if (state == NULL)
 4165 tgl@sss.pgh.pa.us        5805         [ #  # ]:UBC           0 :         elog(ERROR, "int2_accum_inv called with NULL state");
                               5806                 :                : 
 4165 tgl@sss.pgh.pa.us        5807         [ +  + ]:CBC          81 :     if (!PG_ARGISNULL(1))
   30 dean.a.rasheed@gmail     5808                 :GNC          72 :         do_int128_discard(state, PG_GETARG_INT16(1));
                               5809                 :                : 
 4312 tgl@sss.pgh.pa.us        5810                 :CBC          81 :     PG_RETURN_POINTER(state);
                               5811                 :                : }
                               5812                 :                : 
                               5813                 :                : Datum
 4165                          5814                 :             81 : int4_accum_inv(PG_FUNCTION_ARGS)
                               5815                 :                : {
                               5816                 :                :     Int128AggState *state;
                               5817                 :                : 
   30 dean.a.rasheed@gmail     5818         [ +  - ]:GNC          81 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5819                 :                : 
                               5820                 :                :     /* Should not get here with no state */
 4165 tgl@sss.pgh.pa.us        5821         [ -  + ]:CBC          81 :     if (state == NULL)
 4165 tgl@sss.pgh.pa.us        5822         [ #  # ]:UBC           0 :         elog(ERROR, "int4_accum_inv called with NULL state");
                               5823                 :                : 
 4165 tgl@sss.pgh.pa.us        5824         [ +  + ]:CBC          81 :     if (!PG_ARGISNULL(1))
   30 dean.a.rasheed@gmail     5825                 :GNC          72 :         do_int128_discard(state, PG_GETARG_INT32(1));
                               5826                 :                : 
 4165 tgl@sss.pgh.pa.us        5827                 :CBC          81 :     PG_RETURN_POINTER(state);
                               5828                 :                : }
                               5829                 :                : 
                               5830                 :                : Datum
                               5831                 :             81 : int8_accum_inv(PG_FUNCTION_ARGS)
                               5832                 :                : {
                               5833                 :                :     NumericAggState *state;
                               5834                 :                : 
                               5835         [ +  - ]:             81 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5836                 :                : 
                               5837                 :                :     /* Should not get here with no state */
                               5838         [ -  + ]:             81 :     if (state == NULL)
 4165 tgl@sss.pgh.pa.us        5839         [ #  # ]:UBC           0 :         elog(ERROR, "int8_accum_inv called with NULL state");
                               5840                 :                : 
 4165 tgl@sss.pgh.pa.us        5841         [ +  + ]:CBC          81 :     if (!PG_ARGISNULL(1))
                               5842                 :                :     {
                               5843                 :                :         /* Should never fail, all inputs have dscale 0 */
 1823 peter@eisentraut.org     5844         [ -  + ]:             72 :         if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
 4165 tgl@sss.pgh.pa.us        5845         [ #  # ]:UBC           0 :             elog(ERROR, "do_numeric_discard failed unexpectedly");
                               5846                 :                :     }
                               5847                 :                : 
 4165 tgl@sss.pgh.pa.us        5848                 :CBC          81 :     PG_RETURN_POINTER(state);
                               5849                 :                : }
                               5850                 :                : 
                               5851                 :                : Datum
 3823 andres@anarazel.de       5852                 :             18 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
                               5853                 :                : {
                               5854                 :                :     Int128AggState *state;
                               5855                 :                : 
   30 dean.a.rasheed@gmail     5856         [ +  - ]:GNC          18 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5857                 :                : 
                               5858                 :                :     /* Should not get here with no state */
 3823 andres@anarazel.de       5859         [ -  + ]:CBC          18 :     if (state == NULL)
 3823 andres@anarazel.de       5860         [ #  # ]:UBC           0 :         elog(ERROR, "int8_avg_accum_inv called with NULL state");
                               5861                 :                : 
 3823 andres@anarazel.de       5862         [ +  + ]:CBC          18 :     if (!PG_ARGISNULL(1))
   30 dean.a.rasheed@gmail     5863                 :GNC          12 :         do_int128_discard(state, PG_GETARG_INT64(1));
                               5864                 :                : 
 3823 andres@anarazel.de       5865                 :CBC          18 :     PG_RETURN_POINTER(state);
                               5866                 :                : }
                               5867                 :                : 
                               5868                 :                : Datum
                               5869                 :            525 : numeric_poly_sum(PG_FUNCTION_ARGS)
                               5870                 :                : {
                               5871                 :                :     Int128AggState *state;
                               5872                 :                :     Numeric     res;
                               5873                 :                :     NumericVar  result;
                               5874                 :                : 
   30 dean.a.rasheed@gmail     5875         [ +  + ]:GNC         525 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5876                 :                : 
                               5877                 :                :     /* If there were no non-null inputs, return NULL */
 3823 andres@anarazel.de       5878   [ +  +  +  + ]:CBC         525 :     if (state == NULL || state->N == 0)
                               5879                 :             12 :         PG_RETURN_NULL();
                               5880                 :                : 
                               5881                 :            513 :     init_var(&result);
                               5882                 :                : 
                               5883                 :            513 :     int128_to_numericvar(state->sumX, &result);
                               5884                 :                : 
                               5885                 :            513 :     res = make_result(&result);
                               5886                 :                : 
                               5887                 :            513 :     free_var(&result);
                               5888                 :                : 
                               5889                 :            513 :     PG_RETURN_NUMERIC(res);
                               5890                 :                : }
                               5891                 :                : 
                               5892                 :                : Datum
                               5893                 :             18 : numeric_poly_avg(PG_FUNCTION_ARGS)
                               5894                 :                : {
                               5895                 :                :     Int128AggState *state;
                               5896                 :                :     NumericVar  result;
                               5897                 :                :     Datum       countd,
                               5898                 :                :                 sumd;
                               5899                 :                : 
   30 dean.a.rasheed@gmail     5900         [ +  - ]:GNC          18 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               5901                 :                : 
                               5902                 :                :     /* If there were no non-null inputs, return NULL */
 3823 andres@anarazel.de       5903   [ +  -  +  + ]:CBC          18 :     if (state == NULL || state->N == 0)
                               5904                 :              9 :         PG_RETURN_NULL();
                               5905                 :                : 
                               5906                 :              9 :     init_var(&result);
                               5907                 :                : 
                               5908                 :              9 :     int128_to_numericvar(state->sumX, &result);
                               5909                 :                : 
 1823 peter@eisentraut.org     5910                 :              9 :     countd = NumericGetDatum(int64_to_numeric(state->N));
 3823 andres@anarazel.de       5911                 :              9 :     sumd = NumericGetDatum(make_result(&result));
                               5912                 :                : 
                               5913                 :              9 :     free_var(&result);
                               5914                 :                : 
                               5915                 :              9 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
                               5916                 :                : }
                               5917                 :                : 
                               5918                 :                : Datum
 9182 tgl@sss.pgh.pa.us        5919                 :             39 : numeric_avg(PG_FUNCTION_ARGS)
                               5920                 :                : {
                               5921                 :                :     NumericAggState *state;
                               5922                 :                :     Datum       N_datum;
                               5923                 :                :     Datum       sumX_datum;
                               5924                 :                :     NumericVar  sumX_var;
                               5925                 :                : 
 4312                          5926         [ +  - ]:             39 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5927                 :                : 
                               5928                 :                :     /* If there were no non-null inputs, return NULL */
 1872                          5929   [ +  -  +  + ]:             39 :     if (state == NULL || NA_TOTAL_COUNT(state) == 0)
 4312                          5930                 :              9 :         PG_RETURN_NULL();
                               5931                 :                : 
 4141 bruce@momjian.us         5932         [ +  + ]:             30 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
 4312 tgl@sss.pgh.pa.us        5933                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               5934                 :                : 
                               5935                 :                :     /* adding plus and minus infinities gives NaN */
 1872                          5936   [ +  +  +  + ]:             27 :     if (state->pInfcount > 0 && state->nInfcount > 0)
                               5937                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               5938         [ +  + ]:             24 :     if (state->pInfcount > 0)
                               5939                 :              9 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
                               5940         [ +  + ]:             15 :     if (state->nInfcount > 0)
                               5941                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_ninf));
                               5942                 :                : 
 1823 peter@eisentraut.org     5943                 :             12 :     N_datum = NumericGetDatum(int64_to_numeric(state->N));
                               5944                 :                : 
 3291 heikki.linnakangas@i     5945                 :             12 :     init_var(&sumX_var);
                               5946                 :             12 :     accum_sum_final(&state->sumX, &sumX_var);
                               5947                 :             12 :     sumX_datum = NumericGetDatum(make_result(&sumX_var));
                               5948                 :             12 :     free_var(&sumX_var);
                               5949                 :                : 
 4312 tgl@sss.pgh.pa.us        5950                 :             12 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
                               5951                 :                : }
                               5952                 :                : 
                               5953                 :                : Datum
                               5954                 :          85453 : numeric_sum(PG_FUNCTION_ARGS)
                               5955                 :                : {
                               5956                 :                :     NumericAggState *state;
                               5957                 :                :     NumericVar  sumX_var;
                               5958                 :                :     Numeric     result;
                               5959                 :                : 
                               5960         [ +  - ]:          85453 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               5961                 :                : 
                               5962                 :                :     /* If there were no non-null inputs, return NULL */
 1872                          5963   [ +  -  +  + ]:          85453 :     if (state == NULL || NA_TOTAL_COUNT(state) == 0)
 9182                          5964                 :              9 :         PG_RETURN_NULL();
                               5965                 :                : 
 4141 bruce@momjian.us         5966         [ +  + ]:          85444 :     if (state->NaNcount > 0)  /* there was at least one NaN input */
 4312 tgl@sss.pgh.pa.us        5967                 :              9 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               5968                 :                : 
                               5969                 :                :     /* adding plus and minus infinities gives NaN */
 1872                          5970   [ +  +  +  + ]:          85435 :     if (state->pInfcount > 0 && state->nInfcount > 0)
                               5971                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_nan));
                               5972         [ +  + ]:          85432 :     if (state->pInfcount > 0)
                               5973                 :              9 :         PG_RETURN_NUMERIC(make_result(&const_pinf));
                               5974         [ +  + ]:          85423 :     if (state->nInfcount > 0)
                               5975                 :              3 :         PG_RETURN_NUMERIC(make_result(&const_ninf));
                               5976                 :                : 
 3291 heikki.linnakangas@i     5977                 :          85420 :     init_var(&sumX_var);
                               5978                 :          85420 :     accum_sum_final(&state->sumX, &sumX_var);
                               5979                 :          85420 :     result = make_result(&sumX_var);
                               5980                 :          85420 :     free_var(&sumX_var);
                               5981                 :                : 
                               5982                 :          85420 :     PG_RETURN_NUMERIC(result);
                               5983                 :                : }
                               5984                 :                : 
                               5985                 :                : /*
                               5986                 :                :  * Workhorse routine for the standard deviance and variance
                               5987                 :                :  * aggregates. 'state' is aggregate's transition state.
                               5988                 :                :  * 'variance' specifies whether we should calculate the
                               5989                 :                :  * variance or the standard deviation. 'sample' indicates whether the
                               5990                 :                :  * caller is interested in the sample or the population
                               5991                 :                :  * variance/stddev.
                               5992                 :                :  *
                               5993                 :                :  * If appropriate variance statistic is undefined for the input,
                               5994                 :                :  * *is_null is set to true and NULL is returned.
                               5995                 :                :  */
                               5996                 :                : static Numeric
 4312 tgl@sss.pgh.pa.us        5997                 :            493 : numeric_stddev_internal(NumericAggState *state,
                               5998                 :                :                         bool variance, bool sample,
                               5999                 :                :                         bool *is_null)
                               6000                 :                : {
                               6001                 :                :     Numeric     res;
                               6002                 :                :     NumericVar  vN,
                               6003                 :                :                 vsumX,
                               6004                 :                :                 vsumX2,
                               6005                 :                :                 vNminus1;
                               6006                 :                :     int64       totCount;
                               6007                 :                :     int         rscale;
                               6008                 :                : 
                               6009                 :                :     /*
                               6010                 :                :      * Sample stddev and variance are undefined when N <= 1; population stddev
                               6011                 :                :      * is undefined when N == 0.  Return NULL in either case (note that NaNs
                               6012                 :                :      * and infinities count as normal inputs for this purpose).
                               6013                 :                :      */
 1872                          6014   [ +  -  -  + ]:            493 :     if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
                               6015                 :                :     {
 1911 tgl@sss.pgh.pa.us        6016                 :UBC           0 :         *is_null = true;
                               6017                 :              0 :         return NULL;
                               6018                 :                :     }
                               6019                 :                : 
 1911 tgl@sss.pgh.pa.us        6020   [ +  +  +  + ]:CBC         493 :     if (sample && totCount <= 1)
                               6021                 :                :     {
 4312                          6022                 :             66 :         *is_null = true;
                               6023                 :             66 :         return NULL;
                               6024                 :                :     }
                               6025                 :                : 
 7120 neilc@samurai.com        6026                 :            427 :     *is_null = false;
                               6027                 :                : 
                               6028                 :                :     /*
                               6029                 :                :      * Deal with NaN and infinity cases.  By analogy to the behavior of the
                               6030                 :                :      * float8 functions, any infinity input produces NaN output.
                               6031                 :                :      */
 1872 tgl@sss.pgh.pa.us        6032   [ +  +  +  +  :            427 :     if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
                                              +  + ]
 7120 neilc@samurai.com        6033                 :             27 :         return make_result(&const_nan);
                               6034                 :                : 
                               6035                 :                :     /* OK, normal calculation applies */
 4312 tgl@sss.pgh.pa.us        6036                 :            400 :     init_var(&vN);
                               6037                 :            400 :     init_var(&vsumX);
                               6038                 :            400 :     init_var(&vsumX2);
                               6039                 :                : 
 3823 andres@anarazel.de       6040                 :            400 :     int64_to_numericvar(state->N, &vN);
 3291 heikki.linnakangas@i     6041                 :            400 :     accum_sum_final(&(state->sumX), &vsumX);
                               6042                 :            400 :     accum_sum_final(&(state->sumX2), &vsumX2);
                               6043                 :                : 
 8174 tgl@sss.pgh.pa.us        6044                 :            400 :     init_var(&vNminus1);
                               6045                 :            400 :     sub_var(&vN, &const_one, &vNminus1);
                               6046                 :                : 
                               6047                 :                :     /* compute rscale for mul_var calls */
 8205                          6048                 :            400 :     rscale = vsumX.dscale * 2;
                               6049                 :                : 
                               6050                 :            400 :     mul_var(&vsumX, &vsumX, &vsumX, rscale);    /* vsumX = sumX * sumX */
 2999                          6051                 :            400 :     mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
 6912 bruce@momjian.us         6052                 :            400 :     sub_var(&vsumX2, &vsumX, &vsumX2);  /* N * sumX2 - sumX * sumX */
                               6053                 :                : 
 8670 tgl@sss.pgh.pa.us        6054         [ +  + ]:            400 :     if (cmp_var(&vsumX2, &const_zero) <= 0)
                               6055                 :                :     {
                               6056                 :                :         /* Watch out for roundoff error producing a negative numerator */
                               6057                 :             40 :         res = make_result(&const_zero);
                               6058                 :                :     }
                               6059                 :                :     else
                               6060                 :                :     {
 6634                          6061         [ +  + ]:            360 :         if (sample)
 2999                          6062                 :            246 :             mul_var(&vN, &vNminus1, &vNminus1, 0);  /* N * (N - 1) */
                               6063                 :                :         else
 6505 bruce@momjian.us         6064                 :            114 :             mul_var(&vN, &vN, &vNminus1, 0);    /* N * N */
 8205 tgl@sss.pgh.pa.us        6065                 :            360 :         rscale = select_div_scale(&vsumX2, &vNminus1);
  337 dean.a.rasheed@gmail     6066                 :            360 :         div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true);    /* variance */
 7120 neilc@samurai.com        6067         [ +  + ]:            360 :         if (!variance)
 6912 bruce@momjian.us         6068                 :            189 :             sqrt_var(&vsumX, &vsumX, rscale);   /* stddev */
                               6069                 :                : 
 8670 tgl@sss.pgh.pa.us        6070                 :            360 :         res = make_result(&vsumX);
                               6071                 :                :     }
                               6072                 :                : 
 9182                          6073                 :            400 :     free_var(&vNminus1);
                               6074                 :            400 :     free_var(&vsumX);
                               6075                 :            400 :     free_var(&vsumX2);
                               6076                 :                : 
 7120 neilc@samurai.com        6077                 :            400 :     return res;
                               6078                 :                : }
                               6079                 :                : 
                               6080                 :                : Datum
                               6081                 :             90 : numeric_var_samp(PG_FUNCTION_ARGS)
                               6082                 :                : {
                               6083                 :                :     NumericAggState *state;
                               6084                 :                :     Numeric     res;
                               6085                 :                :     bool        is_null;
                               6086                 :                : 
 4312 tgl@sss.pgh.pa.us        6087         [ +  - ]:             90 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6088                 :                : 
                               6089                 :             90 :     res = numeric_stddev_internal(state, true, true, &is_null);
                               6090                 :                : 
 7120 neilc@samurai.com        6091         [ +  + ]:             90 :     if (is_null)
 8174 tgl@sss.pgh.pa.us        6092                 :             21 :         PG_RETURN_NULL();
                               6093                 :                :     else
 7120 neilc@samurai.com        6094                 :             69 :         PG_RETURN_NUMERIC(res);
                               6095                 :                : }
                               6096                 :                : 
                               6097                 :                : Datum
                               6098                 :             87 : numeric_stddev_samp(PG_FUNCTION_ARGS)
                               6099                 :                : {
                               6100                 :                :     NumericAggState *state;
                               6101                 :                :     Numeric     res;
                               6102                 :                :     bool        is_null;
                               6103                 :                : 
 4312 tgl@sss.pgh.pa.us        6104         [ +  - ]:             87 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6105                 :                : 
                               6106                 :             87 :     res = numeric_stddev_internal(state, false, true, &is_null);
                               6107                 :                : 
 7120 neilc@samurai.com        6108         [ +  + ]:             87 :     if (is_null)
                               6109                 :             21 :         PG_RETURN_NULL();
                               6110                 :                :     else
                               6111                 :             66 :         PG_RETURN_NUMERIC(res);
                               6112                 :                : }
                               6113                 :                : 
                               6114                 :                : Datum
                               6115                 :             57 : numeric_var_pop(PG_FUNCTION_ARGS)
                               6116                 :                : {
                               6117                 :                :     NumericAggState *state;
                               6118                 :                :     Numeric     res;
                               6119                 :                :     bool        is_null;
                               6120                 :                : 
 4312 tgl@sss.pgh.pa.us        6121         [ +  - ]:             57 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6122                 :                : 
                               6123                 :             57 :     res = numeric_stddev_internal(state, true, false, &is_null);
                               6124                 :                : 
 7120 neilc@samurai.com        6125         [ -  + ]:             57 :     if (is_null)
 7120 neilc@samurai.com        6126                 :UBC           0 :         PG_RETURN_NULL();
                               6127                 :                :     else
 7120 neilc@samurai.com        6128                 :CBC          57 :         PG_RETURN_NUMERIC(res);
                               6129                 :                : }
                               6130                 :                : 
                               6131                 :                : Datum
                               6132                 :             48 : numeric_stddev_pop(PG_FUNCTION_ARGS)
                               6133                 :                : {
                               6134                 :                :     NumericAggState *state;
                               6135                 :                :     Numeric     res;
                               6136                 :                :     bool        is_null;
                               6137                 :                : 
 4312 tgl@sss.pgh.pa.us        6138         [ +  - ]:             48 :     state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
                               6139                 :                : 
                               6140                 :             48 :     res = numeric_stddev_internal(state, false, false, &is_null);
                               6141                 :                : 
 7120 neilc@samurai.com        6142         [ -  + ]:             48 :     if (is_null)
 7120 neilc@samurai.com        6143                 :UBC           0 :         PG_RETURN_NULL();
                               6144                 :                :     else
 7120 neilc@samurai.com        6145                 :CBC          48 :         PG_RETURN_NUMERIC(res);
                               6146                 :                : }
                               6147                 :                : 
                               6148                 :                : static Numeric
 3823 andres@anarazel.de       6149                 :            211 : numeric_poly_stddev_internal(Int128AggState *state,
                               6150                 :                :                              bool variance, bool sample,
                               6151                 :                :                              bool *is_null)
                               6152                 :                : {
                               6153                 :                :     NumericAggState numstate;
                               6154                 :                :     Numeric     res;
                               6155                 :                : 
                               6156                 :                :     /* Initialize an empty agg state */
 3291 heikki.linnakangas@i     6157                 :            211 :     memset(&numstate, 0, sizeof(NumericAggState));
                               6158                 :                : 
 3823 andres@anarazel.de       6159         [ +  - ]:            211 :     if (state)
                               6160                 :                :     {
                               6161                 :                :         NumericVar  tmp_var;
                               6162                 :                : 
                               6163                 :            211 :         numstate.N = state->N;
                               6164                 :                : 
 3291 heikki.linnakangas@i     6165                 :            211 :         init_var(&tmp_var);
                               6166                 :                : 
                               6167                 :            211 :         int128_to_numericvar(state->sumX, &tmp_var);
                               6168                 :            211 :         accum_sum_add(&numstate.sumX, &tmp_var);
                               6169                 :                : 
                               6170                 :            211 :         int128_to_numericvar(state->sumX2, &tmp_var);
                               6171                 :            211 :         accum_sum_add(&numstate.sumX2, &tmp_var);
                               6172                 :                : 
                               6173                 :            211 :         free_var(&tmp_var);
                               6174                 :                :     }
                               6175                 :                : 
 3823 andres@anarazel.de       6176                 :            211 :     res = numeric_stddev_internal(&numstate, variance, sample, is_null);
                               6177                 :                : 
 3291 heikki.linnakangas@i     6178         [ +  - ]:            211 :     if (numstate.sumX.ndigits > 0)
                               6179                 :                :     {
                               6180                 :            211 :         pfree(numstate.sumX.pos_digits);
                               6181                 :            211 :         pfree(numstate.sumX.neg_digits);
                               6182                 :                :     }
                               6183         [ +  - ]:            211 :     if (numstate.sumX2.ndigits > 0)
                               6184                 :                :     {
                               6185                 :            211 :         pfree(numstate.sumX2.pos_digits);
                               6186                 :            211 :         pfree(numstate.sumX2.neg_digits);
                               6187                 :                :     }
                               6188                 :                : 
 3823 andres@anarazel.de       6189                 :            211 :     return res;
                               6190                 :                : }
                               6191                 :                : 
                               6192                 :                : Datum
                               6193                 :             63 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
                               6194                 :                : {
                               6195                 :                :     Int128AggState *state;
                               6196                 :                :     Numeric     res;
                               6197                 :                :     bool        is_null;
                               6198                 :                : 
   30 dean.a.rasheed@gmail     6199         [ +  - ]:GNC          63 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               6200                 :                : 
 3823 andres@anarazel.de       6201                 :CBC          63 :     res = numeric_poly_stddev_internal(state, true, true, &is_null);
                               6202                 :                : 
                               6203         [ +  + ]:             63 :     if (is_null)
                               6204                 :             12 :         PG_RETURN_NULL();
                               6205                 :                :     else
                               6206                 :             51 :         PG_RETURN_NUMERIC(res);
                               6207                 :                : }
                               6208                 :                : 
                               6209                 :                : Datum
                               6210                 :             82 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
                               6211                 :                : {
                               6212                 :                :     Int128AggState *state;
                               6213                 :                :     Numeric     res;
                               6214                 :                :     bool        is_null;
                               6215                 :                : 
   30 dean.a.rasheed@gmail     6216         [ +  - ]:GNC          82 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               6217                 :                : 
 3823 andres@anarazel.de       6218                 :CBC          82 :     res = numeric_poly_stddev_internal(state, false, true, &is_null);
                               6219                 :                : 
                               6220         [ +  + ]:             82 :     if (is_null)
                               6221                 :             12 :         PG_RETURN_NULL();
                               6222                 :                :     else
                               6223                 :             70 :         PG_RETURN_NUMERIC(res);
                               6224                 :                : }
                               6225                 :                : 
                               6226                 :                : Datum
                               6227                 :             30 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
                               6228                 :                : {
                               6229                 :                :     Int128AggState *state;
                               6230                 :                :     Numeric     res;
                               6231                 :                :     bool        is_null;
                               6232                 :                : 
   30 dean.a.rasheed@gmail     6233         [ +  - ]:GNC          30 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               6234                 :                : 
 3823 andres@anarazel.de       6235                 :CBC          30 :     res = numeric_poly_stddev_internal(state, true, false, &is_null);
                               6236                 :                : 
                               6237         [ -  + ]:             30 :     if (is_null)
 3823 andres@anarazel.de       6238                 :UBC           0 :         PG_RETURN_NULL();
                               6239                 :                :     else
 3823 andres@anarazel.de       6240                 :CBC          30 :         PG_RETURN_NUMERIC(res);
                               6241                 :                : }
                               6242                 :                : 
                               6243                 :                : Datum
                               6244                 :             36 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
                               6245                 :                : {
                               6246                 :                :     Int128AggState *state;
                               6247                 :                :     Numeric     res;
                               6248                 :                :     bool        is_null;
                               6249                 :                : 
   30 dean.a.rasheed@gmail     6250         [ +  - ]:GNC          36 :     state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
                               6251                 :                : 
 3823 andres@anarazel.de       6252                 :CBC          36 :     res = numeric_poly_stddev_internal(state, false, false, &is_null);
                               6253                 :                : 
                               6254         [ -  + ]:             36 :     if (is_null)
 3823 andres@anarazel.de       6255                 :UBC           0 :         PG_RETURN_NULL();
                               6256                 :                :     else
 3823 andres@anarazel.de       6257                 :CBC          36 :         PG_RETURN_NUMERIC(res);
                               6258                 :                : }
                               6259                 :                : 
                               6260                 :                : /*
                               6261                 :                :  * SUM transition functions for integer datatypes.
                               6262                 :                :  *
                               6263                 :                :  * To avoid overflow, we use accumulators wider than the input datatype.
                               6264                 :                :  * A Numeric accumulator is needed for int8 input; for int4 and int2
                               6265                 :                :  * inputs, we use int8 accumulators which should be sufficient for practical
                               6266                 :                :  * purposes.  (The latter two therefore don't really belong in this file,
                               6267                 :                :  * but we keep them here anyway.)
                               6268                 :                :  *
                               6269                 :                :  * Because SQL defines the SUM() of no values to be NULL, not zero,
                               6270                 :                :  * the initial condition of the transition data value needs to be NULL. This
                               6271                 :                :  * means we can't rely on ExecAgg to automatically insert the first non-null
                               6272                 :                :  * data value into the transition data: it doesn't know how to do the type
                               6273                 :                :  * conversion.  The upshot is that these routines have to be marked non-strict
                               6274                 :                :  * and handle substitution of the first non-null input themselves.
                               6275                 :                :  *
                               6276                 :                :  * Note: these functions are used only in plain aggregation mode.
                               6277                 :                :  * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
                               6278                 :                :  */
                               6279                 :                : 
                               6280                 :                : Datum
 9182 tgl@sss.pgh.pa.us        6281                 :             12 : int2_sum(PG_FUNCTION_ARGS)
                               6282                 :                : {
                               6283                 :                :     int64       oldsum;
                               6284                 :                :     int64       newval;
                               6285                 :                : 
                               6286         [ +  + ]:             12 :     if (PG_ARGISNULL(0))
                               6287                 :                :     {
                               6288                 :                :         /* No non-null input seen so far... */
                               6289         [ -  + ]:              3 :         if (PG_ARGISNULL(1))
 9182 tgl@sss.pgh.pa.us        6290                 :UBC           0 :             PG_RETURN_NULL();   /* still no non-null */
                               6291                 :                :         /* This is the first non-null input. */
 8789 tgl@sss.pgh.pa.us        6292                 :CBC           3 :         newval = (int64) PG_GETARG_INT16(1);
                               6293                 :              3 :         PG_RETURN_INT64(newval);
                               6294                 :                :     }
                               6295                 :                : 
   24 tgl@sss.pgh.pa.us        6296                 :GNC           9 :     oldsum = PG_GETARG_INT64(0);
                               6297                 :                : 
                               6298                 :                :     /* Leave sum unchanged if new input is null. */
                               6299         [ -  + ]:              9 :     if (PG_ARGISNULL(1))
   24 tgl@sss.pgh.pa.us        6300                 :UNC           0 :         PG_RETURN_INT64(oldsum);
                               6301                 :                : 
                               6302                 :                :     /* OK to do the addition. */
   24 tgl@sss.pgh.pa.us        6303                 :GNC           9 :     newval = oldsum + (int64) PG_GETARG_INT16(1);
                               6304                 :                : 
                               6305                 :              9 :     PG_RETURN_INT64(newval);
                               6306                 :                : }
                               6307                 :                : 
                               6308                 :                : Datum
 9182 tgl@sss.pgh.pa.us        6309                 :CBC     1849078 : int4_sum(PG_FUNCTION_ARGS)
                               6310                 :                : {
                               6311                 :                :     int64       oldsum;
                               6312                 :                :     int64       newval;
                               6313                 :                : 
                               6314         [ +  + ]:        1849078 :     if (PG_ARGISNULL(0))
                               6315                 :                :     {
                               6316                 :                :         /* No non-null input seen so far... */
                               6317         [ +  + ]:         103735 :         if (PG_ARGISNULL(1))
                               6318                 :            493 :             PG_RETURN_NULL();   /* still no non-null */
                               6319                 :                :         /* This is the first non-null input. */
 8789                          6320                 :         103242 :         newval = (int64) PG_GETARG_INT32(1);
                               6321                 :         103242 :         PG_RETURN_INT64(newval);
                               6322                 :                :     }
                               6323                 :                : 
   24 tgl@sss.pgh.pa.us        6324                 :GNC     1745343 :     oldsum = PG_GETARG_INT64(0);
                               6325                 :                : 
                               6326                 :                :     /* Leave sum unchanged if new input is null. */
                               6327         [ +  + ]:        1745343 :     if (PG_ARGISNULL(1))
                               6328                 :          15437 :         PG_RETURN_INT64(oldsum);
                               6329                 :                : 
                               6330                 :                :     /* OK to do the addition. */
                               6331                 :        1729906 :     newval = oldsum + (int64) PG_GETARG_INT32(1);
                               6332                 :                : 
                               6333                 :        1729906 :     PG_RETURN_INT64(newval);
                               6334                 :                : }
                               6335                 :                : 
                               6336                 :                : /*
                               6337                 :                :  * Note: this function is obsolete, it's no longer used for SUM(int8).
                               6338                 :                :  */
                               6339                 :                : Datum
 9182 tgl@sss.pgh.pa.us        6340                 :UBC           0 : int8_sum(PG_FUNCTION_ARGS)
                               6341                 :                : {
                               6342                 :                :     Numeric     oldsum;
                               6343                 :                : 
                               6344         [ #  # ]:              0 :     if (PG_ARGISNULL(0))
                               6345                 :                :     {
                               6346                 :                :         /* No non-null input seen so far... */
                               6347         [ #  # ]:              0 :         if (PG_ARGISNULL(1))
                               6348                 :              0 :             PG_RETURN_NULL();   /* still no non-null */
                               6349                 :                :         /* This is the first non-null input. */
 1823 peter@eisentraut.org     6350                 :              0 :         PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
                               6351                 :                :     }
                               6352                 :                : 
                               6353                 :                :     /*
                               6354                 :                :      * Note that we cannot special-case the aggregate case here, as we do for
                               6355                 :                :      * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
                               6356                 :                :      * our first parameter in-place.
                               6357                 :                :      */
                               6358                 :                : 
 9182 tgl@sss.pgh.pa.us        6359                 :              0 :     oldsum = PG_GETARG_NUMERIC(0);
                               6360                 :                : 
                               6361                 :                :     /* Leave sum unchanged if new input is null. */
                               6362         [ #  # ]:              0 :     if (PG_ARGISNULL(1))
                               6363                 :              0 :         PG_RETURN_NUMERIC(oldsum);
                               6364                 :                : 
                               6365                 :                :     /* OK to do the addition. */
 9170                          6366                 :              0 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
                               6367                 :                :                                         NumericGetDatum(oldsum),
                               6368                 :                :                                         NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
                               6369                 :                : }
                               6370                 :                : 
                               6371                 :                : 
                               6372                 :                : /*
                               6373                 :                :  * Routines for avg(int2) and avg(int4).  The transition datatype
                               6374                 :                :  * is a two-element int8 array, holding count and sum.
                               6375                 :                :  *
                               6376                 :                :  * These functions are also used for sum(int2) and sum(int4) when
                               6377                 :                :  * operating in moving-aggregate mode, since for correct inverse transitions
                               6378                 :                :  * we need to count the inputs.
                               6379                 :                :  */
                               6380                 :                : 
                               6381                 :                : typedef struct Int8TransTypeData
                               6382                 :                : {
                               6383                 :                :     int64       count;
                               6384                 :                :     int64       sum;
                               6385                 :                : } Int8TransTypeData;
                               6386                 :                : 
                               6387                 :                : Datum
 8789 tgl@sss.pgh.pa.us        6388                 :CBC          21 : int2_avg_accum(PG_FUNCTION_ARGS)
                               6389                 :                : {
                               6390                 :                :     ArrayType  *transarray;
                               6391                 :             21 :     int16       newval = PG_GETARG_INT16(1);
                               6392                 :                :     Int8TransTypeData *transdata;
                               6393                 :                : 
                               6394                 :                :     /*
                               6395                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6396                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6397                 :                :      * a copy of it before scribbling on it.
                               6398                 :                :      */
 5689                          6399         [ +  - ]:             21 :     if (AggCheckCallContext(fcinfo, NULL))
 7460 neilc@samurai.com        6400                 :             21 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6401                 :                :     else
 7460 neilc@samurai.com        6402                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6403                 :                : 
 7233 tgl@sss.pgh.pa.us        6404   [ +  -  -  + ]:CBC          42 :     if (ARR_HASNULL(transarray) ||
                               6405         [ -  + ]:             21 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 8077 tgl@sss.pgh.pa.us        6406         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6407                 :                : 
 7460 neilc@samurai.com        6408         [ -  + ]:CBC          21 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
 8789 tgl@sss.pgh.pa.us        6409                 :             21 :     transdata->count++;
                               6410                 :             21 :     transdata->sum += newval;
                               6411                 :                : 
                               6412                 :             21 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6413                 :                : }
                               6414                 :                : 
                               6415                 :                : Datum
                               6416                 :        1310151 : int4_avg_accum(PG_FUNCTION_ARGS)
                               6417                 :                : {
                               6418                 :                :     ArrayType  *transarray;
                               6419                 :        1310151 :     int32       newval = PG_GETARG_INT32(1);
                               6420                 :                :     Int8TransTypeData *transdata;
                               6421                 :                : 
                               6422                 :                :     /*
                               6423                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6424                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6425                 :                :      * a copy of it before scribbling on it.
                               6426                 :                :      */
 5689                          6427         [ +  - ]:        1310151 :     if (AggCheckCallContext(fcinfo, NULL))
 7460 neilc@samurai.com        6428                 :        1310151 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6429                 :                :     else
 7460 neilc@samurai.com        6430                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6431                 :                : 
 7233 tgl@sss.pgh.pa.us        6432   [ +  -  -  + ]:CBC     2620302 :     if (ARR_HASNULL(transarray) ||
                               6433         [ -  + ]:        1310151 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 8077 tgl@sss.pgh.pa.us        6434         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6435                 :                : 
 7460 neilc@samurai.com        6436         [ -  + ]:CBC     1310151 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
 8789 tgl@sss.pgh.pa.us        6437                 :        1310151 :     transdata->count++;
                               6438                 :        1310151 :     transdata->sum += newval;
                               6439                 :                : 
                               6440                 :        1310151 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6441                 :                : }
                               6442                 :                : 
                               6443                 :                : Datum
 3441 rhaas@postgresql.org     6444                 :           2187 : int4_avg_combine(PG_FUNCTION_ARGS)
                               6445                 :                : {
                               6446                 :                :     ArrayType  *transarray1;
                               6447                 :                :     ArrayType  *transarray2;
                               6448                 :                :     Int8TransTypeData *state1;
                               6449                 :                :     Int8TransTypeData *state2;
                               6450                 :                : 
                               6451         [ -  + ]:           2187 :     if (!AggCheckCallContext(fcinfo, NULL))
 3441 rhaas@postgresql.org     6452         [ #  # ]:UBC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
                               6453                 :                : 
 3441 rhaas@postgresql.org     6454                 :CBC        2187 :     transarray1 = PG_GETARG_ARRAYTYPE_P(0);
                               6455                 :           2187 :     transarray2 = PG_GETARG_ARRAYTYPE_P(1);
                               6456                 :                : 
                               6457   [ +  -  -  + ]:           4374 :     if (ARR_HASNULL(transarray1) ||
                               6458         [ -  + ]:           2187 :         ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 3441 rhaas@postgresql.org     6459         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6460                 :                : 
 3441 rhaas@postgresql.org     6461   [ +  -  -  + ]:CBC        4374 :     if (ARR_HASNULL(transarray2) ||
                               6462         [ -  + ]:           2187 :         ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 3441 rhaas@postgresql.org     6463         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6464                 :                : 
 3441 rhaas@postgresql.org     6465         [ -  + ]:CBC        2187 :     state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
                               6466         [ -  + ]:           2187 :     state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
                               6467                 :                : 
                               6468                 :           2187 :     state1->count += state2->count;
                               6469                 :           2187 :     state1->sum += state2->sum;
                               6470                 :                : 
                               6471                 :           2187 :     PG_RETURN_ARRAYTYPE_P(transarray1);
                               6472                 :                : }
                               6473                 :                : 
                               6474                 :                : Datum
 4165 tgl@sss.pgh.pa.us        6475                 :              6 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
                               6476                 :                : {
                               6477                 :                :     ArrayType  *transarray;
                               6478                 :              6 :     int16       newval = PG_GETARG_INT16(1);
                               6479                 :                :     Int8TransTypeData *transdata;
                               6480                 :                : 
                               6481                 :                :     /*
                               6482                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6483                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6484                 :                :      * a copy of it before scribbling on it.
                               6485                 :                :      */
                               6486         [ +  - ]:              6 :     if (AggCheckCallContext(fcinfo, NULL))
                               6487                 :              6 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6488                 :                :     else
 4165 tgl@sss.pgh.pa.us        6489                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6490                 :                : 
 4165 tgl@sss.pgh.pa.us        6491   [ +  -  -  + ]:CBC          12 :     if (ARR_HASNULL(transarray) ||
                               6492         [ -  + ]:              6 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 4165 tgl@sss.pgh.pa.us        6493         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6494                 :                : 
 4165 tgl@sss.pgh.pa.us        6495         [ -  + ]:CBC           6 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6496                 :              6 :     transdata->count--;
                               6497                 :              6 :     transdata->sum -= newval;
                               6498                 :                : 
                               6499                 :              6 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6500                 :                : }
                               6501                 :                : 
                               6502                 :                : Datum
                               6503                 :            726 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
                               6504                 :                : {
                               6505                 :                :     ArrayType  *transarray;
                               6506                 :            726 :     int32       newval = PG_GETARG_INT32(1);
                               6507                 :                :     Int8TransTypeData *transdata;
                               6508                 :                : 
                               6509                 :                :     /*
                               6510                 :                :      * If we're invoked as an aggregate, we can cheat and modify our first
                               6511                 :                :      * parameter in-place to reduce palloc overhead. Otherwise we need to make
                               6512                 :                :      * a copy of it before scribbling on it.
                               6513                 :                :      */
                               6514         [ +  - ]:            726 :     if (AggCheckCallContext(fcinfo, NULL))
                               6515                 :            726 :         transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6516                 :                :     else
 4165 tgl@sss.pgh.pa.us        6517                 :UBC           0 :         transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
                               6518                 :                : 
 4165 tgl@sss.pgh.pa.us        6519   [ +  -  -  + ]:CBC        1452 :     if (ARR_HASNULL(transarray) ||
                               6520         [ -  + ]:            726 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 4165 tgl@sss.pgh.pa.us        6521         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
                               6522                 :                : 
 4165 tgl@sss.pgh.pa.us        6523         [ -  + ]:CBC         726 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6524                 :            726 :     transdata->count--;
                               6525                 :            726 :     transdata->sum -= newval;
                               6526                 :                : 
                               6527                 :            726 :     PG_RETURN_ARRAYTYPE_P(transarray);
                               6528                 :                : }
                               6529                 :                : 
                               6530                 :                : Datum
 8789                          6531                 :           5387 : int8_avg(PG_FUNCTION_ARGS)
                               6532                 :                : {
                               6533                 :           5387 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6534                 :                :     Int8TransTypeData *transdata;
                               6535                 :                :     Datum       countd,
                               6536                 :                :                 sumd;
                               6537                 :                : 
 7233                          6538   [ +  -  -  + ]:          10774 :     if (ARR_HASNULL(transarray) ||
                               6539         [ -  + ]:           5387 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 8077 tgl@sss.pgh.pa.us        6540         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
 8789 tgl@sss.pgh.pa.us        6541         [ -  + ]:CBC        5387 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6542                 :                : 
                               6543                 :                :     /* SQL defines AVG of no values to be NULL */
                               6544         [ +  + ]:           5387 :     if (transdata->count == 0)
                               6545                 :             59 :         PG_RETURN_NULL();
                               6546                 :                : 
 1823 peter@eisentraut.org     6547                 :           5328 :     countd = NumericGetDatum(int64_to_numeric(transdata->count));
                               6548                 :           5328 :     sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
                               6549                 :                : 
 8789 tgl@sss.pgh.pa.us        6550                 :           5328 :     PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
                               6551                 :                : }
                               6552                 :                : 
                               6553                 :                : /*
                               6554                 :                :  * SUM(int2) and SUM(int4) both return int8, so we can use this
                               6555                 :                :  * final function for both.
                               6556                 :                :  */
                               6557                 :                : Datum
 4165                          6558                 :           1917 : int2int4_sum(PG_FUNCTION_ARGS)
                               6559                 :                : {
                               6560                 :           1917 :     ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
                               6561                 :                :     Int8TransTypeData *transdata;
                               6562                 :                : 
                               6563   [ +  -  -  + ]:           3834 :     if (ARR_HASNULL(transarray) ||
                               6564         [ -  + ]:           1917 :         ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
 4165 tgl@sss.pgh.pa.us        6565         [ #  # ]:UBC           0 :         elog(ERROR, "expected 2-element int8 array");
 4165 tgl@sss.pgh.pa.us        6566         [ -  + ]:CBC        1917 :     transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
                               6567                 :                : 
                               6568                 :                :     /* SQL defines SUM of no values to be NULL */
                               6569         [ +  + ]:           1917 :     if (transdata->count == 0)
                               6570                 :            240 :         PG_RETURN_NULL();
                               6571                 :                : 
                               6572                 :           1677 :     PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
                               6573                 :                : }
                               6574                 :                : 
                               6575                 :                : 
                               6576                 :                : /* ----------------------------------------------------------------------
                               6577                 :                :  *
                               6578                 :                :  * Debug support
                               6579                 :                :  *
                               6580                 :                :  * ----------------------------------------------------------------------
                               6581                 :                :  */
                               6582                 :                : 
                               6583                 :                : #ifdef NUMERIC_DEBUG
                               6584                 :                : 
                               6585                 :                : /*
                               6586                 :                :  * dump_numeric() - Dump a value in the db storage format for debugging
                               6587                 :                :  */
                               6588                 :                : static void
                               6589                 :                : dump_numeric(const char *str, Numeric num)
                               6590                 :                : {
                               6591                 :                :     NumericDigit *digits = NUMERIC_DIGITS(num);
                               6592                 :                :     int         ndigits;
                               6593                 :                :     int         i;
                               6594                 :                : 
                               6595                 :                :     ndigits = NUMERIC_NDIGITS(num);
                               6596                 :                : 
                               6597                 :                :     printf("%s: NUMERIC w=%d d=%d ", str,
                               6598                 :                :            NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
                               6599                 :                :     switch (NUMERIC_SIGN(num))
                               6600                 :                :     {
                               6601                 :                :         case NUMERIC_POS:
                               6602                 :                :             printf("POS");
                               6603                 :                :             break;
                               6604                 :                :         case NUMERIC_NEG:
                               6605                 :                :             printf("NEG");
                               6606                 :                :             break;
                               6607                 :                :         case NUMERIC_NAN:
                               6608                 :                :             printf("NaN");
                               6609                 :                :             break;
                               6610                 :                :         case NUMERIC_PINF:
                               6611                 :                :             printf("Infinity");
                               6612                 :                :             break;
                               6613                 :                :         case NUMERIC_NINF:
                               6614                 :                :             printf("-Infinity");
                               6615                 :                :             break;
                               6616                 :                :         default:
                               6617                 :                :             printf("SIGN=0x%x", NUMERIC_SIGN(num));
                               6618                 :                :             break;
                               6619                 :                :     }
                               6620                 :                : 
                               6621                 :                :     for (i = 0; i < ndigits; i++)
                               6622                 :                :         printf(" %0*d", DEC_DIGITS, digits[i]);
                               6623                 :                :     printf("\n");
                               6624                 :                : }
                               6625                 :                : 
                               6626                 :                : 
                               6627                 :                : /*
                               6628                 :                :  * dump_var() - Dump a value in the variable format for debugging
                               6629                 :                :  */
                               6630                 :                : static void
                               6631                 :                : dump_var(const char *str, NumericVar *var)
                               6632                 :                : {
                               6633                 :                :     int         i;
                               6634                 :                : 
                               6635                 :                :     printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
                               6636                 :                :     switch (var->sign)
                               6637                 :                :     {
                               6638                 :                :         case NUMERIC_POS:
                               6639                 :                :             printf("POS");
                               6640                 :                :             break;
                               6641                 :                :         case NUMERIC_NEG:
                               6642                 :                :             printf("NEG");
                               6643                 :                :             break;
                               6644                 :                :         case NUMERIC_NAN:
                               6645                 :                :             printf("NaN");
                               6646                 :                :             break;
                               6647                 :                :         case NUMERIC_PINF:
                               6648                 :                :             printf("Infinity");
                               6649                 :                :             break;
                               6650                 :                :         case NUMERIC_NINF:
                               6651                 :                :             printf("-Infinity");
                               6652                 :                :             break;
                               6653                 :                :         default:
                               6654                 :                :             printf("SIGN=0x%x", var->sign);
                               6655                 :                :             break;
                               6656                 :                :     }
                               6657                 :                : 
                               6658                 :                :     for (i = 0; i < var->ndigits; i++)
                               6659                 :                :         printf(" %0*d", DEC_DIGITS, var->digits[i]);
                               6660                 :                : 
                               6661                 :                :     printf("\n");
                               6662                 :                : }
                               6663                 :                : #endif                          /* NUMERIC_DEBUG */
                               6664                 :                : 
                               6665                 :                : 
                               6666                 :                : /* ----------------------------------------------------------------------
                               6667                 :                :  *
                               6668                 :                :  * Local functions follow
                               6669                 :                :  *
                               6670                 :                :  * In general, these do not support "special" (NaN or infinity) inputs;
                               6671                 :                :  * callers should handle those possibilities first.
                               6672                 :                :  * (There are one or two exceptions, noted in their header comments.)
                               6673                 :                :  *
                               6674                 :                :  * ----------------------------------------------------------------------
                               6675                 :                :  */
                               6676                 :                : 
                               6677                 :                : 
                               6678                 :                : /*
                               6679                 :                :  * alloc_var() -
                               6680                 :                :  *
                               6681                 :                :  *  Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
                               6682                 :                :  */
                               6683                 :                : static void
 9363                          6684                 :        1088477 : alloc_var(NumericVar *var, int ndigits)
                               6685                 :                : {
                               6686         [ +  + ]:        1088477 :     digitbuf_free(var->buf);
                               6687                 :        1088477 :     var->buf = digitbuf_alloc(ndigits + 1);
 8069 bruce@momjian.us         6688                 :        1088477 :     var->buf[0] = 0;         /* spare digit for rounding */
 9363 tgl@sss.pgh.pa.us        6689                 :        1088477 :     var->digits = var->buf + 1;
                               6690                 :        1088477 :     var->ndigits = ndigits;
 9747 JanWieck@Yahoo.com       6691                 :        1088477 : }
                               6692                 :                : 
                               6693                 :                : 
                               6694                 :                : /*
                               6695                 :                :  * free_var() -
                               6696                 :                :  *
                               6697                 :                :  *  Return the digit buffer of a variable to the free pool
                               6698                 :                :  */
                               6699                 :                : static void
 9601 bruce@momjian.us         6700                 :        2094172 : free_var(NumericVar *var)
                               6701                 :                : {
 9363 tgl@sss.pgh.pa.us        6702         [ +  + ]:        2094172 :     digitbuf_free(var->buf);
                               6703                 :        2094172 :     var->buf = NULL;
                               6704                 :        2094172 :     var->digits = NULL;
 9747 JanWieck@Yahoo.com       6705                 :        2094172 :     var->sign = NUMERIC_NAN;
                               6706                 :        2094172 : }
                               6707                 :                : 
                               6708                 :                : 
                               6709                 :                : /*
                               6710                 :                :  * zero_var() -
                               6711                 :                :  *
                               6712                 :                :  *  Set a variable to ZERO.
                               6713                 :                :  *  Note: its dscale is not touched.
                               6714                 :                :  */
                               6715                 :                : static void
 9363 tgl@sss.pgh.pa.us        6716                 :          30458 : zero_var(NumericVar *var)
                               6717                 :                : {
                               6718         [ +  + ]:          30458 :     digitbuf_free(var->buf);
                               6719                 :          30458 :     var->buf = NULL;
                               6720                 :          30458 :     var->digits = NULL;
                               6721                 :          30458 :     var->ndigits = 0;
                               6722                 :          30458 :     var->weight = 0;         /* by convention; doesn't really matter */
                               6723                 :          30458 :     var->sign = NUMERIC_POS; /* anything but NAN... */
 9747 JanWieck@Yahoo.com       6724                 :          30458 : }
                               6725                 :                : 
                               6726                 :                : 
                               6727                 :                : /*
                               6728                 :                :  * set_var_from_str()
                               6729                 :                :  *
                               6730                 :                :  *  Parse a string and put the number into a variable
                               6731                 :                :  *
                               6732                 :                :  * This function does not handle leading or trailing spaces.  It returns
                               6733                 :                :  * the end+1 position parsed into *endptr, so that caller can check for
                               6734                 :                :  * trailing spaces/garbage if deemed necessary.
                               6735                 :                :  *
                               6736                 :                :  * cp is the place to actually start parsing; str is what to use in error
                               6737                 :                :  * reports.  (Typically cp would be the same except advanced over spaces.)
                               6738                 :                :  *
                               6739                 :                :  * Returns true on success, false on failure (if escontext points to an
                               6740                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               6741                 :                :  */
                               6742                 :                : static bool
 1002 tgl@sss.pgh.pa.us        6743                 :          92659 : set_var_from_str(const char *str, const char *cp,
                               6744                 :                :                  NumericVar *dest, const char **endptr,
                               6745                 :                :                  Node *escontext)
                               6746                 :                : {
 2943 peter_e@gmx.net          6747                 :          92659 :     bool        have_dp = false;
                               6748                 :                :     int         i;
                               6749                 :                :     unsigned char *decdigits;
 8205 tgl@sss.pgh.pa.us        6750                 :          92659 :     int         sign = NUMERIC_POS;
                               6751                 :          92659 :     int         dweight = -1;
                               6752                 :                :     int         ddigits;
                               6753                 :          92659 :     int         dscale = 0;
                               6754                 :                :     int         weight;
                               6755                 :                :     int         ndigits;
                               6756                 :                :     int         offset;
                               6757                 :                :     NumericDigit *digits;
                               6758                 :                : 
                               6759                 :                :     /*
                               6760                 :                :      * We first parse the string to extract decimal digits and determine the
                               6761                 :                :      * correct decimal weight.  Then convert to NBASE representation.
                               6762                 :                :      */
 9747 JanWieck@Yahoo.com       6763      [ -  +  + ]:          92659 :     switch (*cp)
                               6764                 :                :     {
 9601 bruce@momjian.us         6765                 :UBC           0 :         case '+':
 8205 tgl@sss.pgh.pa.us        6766                 :              0 :             sign = NUMERIC_POS;
 9601 bruce@momjian.us         6767                 :              0 :             cp++;
                               6768                 :              0 :             break;
                               6769                 :                : 
 9601 bruce@momjian.us         6770                 :CBC         150 :         case '-':
 8205 tgl@sss.pgh.pa.us        6771                 :            150 :             sign = NUMERIC_NEG;
 9601 bruce@momjian.us         6772                 :            150 :             cp++;
                               6773                 :            150 :             break;
                               6774                 :                :     }
                               6775                 :                : 
 9747 JanWieck@Yahoo.com       6776         [ +  + ]:          92659 :     if (*cp == '.')
                               6777                 :                :     {
 2943 peter_e@gmx.net          6778                 :            191 :         have_dp = true;
 9747 JanWieck@Yahoo.com       6779                 :            191 :         cp++;
                               6780                 :                :     }
                               6781                 :                : 
 9043 tgl@sss.pgh.pa.us        6782         [ -  + ]:          92659 :     if (!isdigit((unsigned char) *cp))
  945 dean.a.rasheed@gmail     6783                 :UBC           0 :         goto invalid_syntax;
                               6784                 :                : 
 8069 bruce@momjian.us         6785                 :CBC       92659 :     decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
                               6786                 :                : 
                               6787                 :                :     /* leading padding for digit alignment later */
 8205 tgl@sss.pgh.pa.us        6788                 :          92659 :     memset(decdigits, 0, DEC_DIGITS);
                               6789                 :          92659 :     i = DEC_DIGITS;
                               6790                 :                : 
 9747 JanWieck@Yahoo.com       6791         [ +  + ]:         407070 :     while (*cp)
                               6792                 :                :     {
 9043 tgl@sss.pgh.pa.us        6793         [ +  + ]:         315093 :         if (isdigit((unsigned char) *cp))
                               6794                 :                :         {
 8205                          6795                 :         305226 :             decdigits[i++] = *cp++ - '0';
 9363                          6796         [ +  + ]:         305226 :             if (!have_dp)
 8205                          6797                 :         256889 :                 dweight++;
                               6798                 :                :             else
                               6799                 :          48337 :                 dscale++;
                               6800                 :                :         }
 9363                          6801         [ +  + ]:           9867 :         else if (*cp == '.')
                               6802                 :                :         {
                               6803         [ -  + ]:           9104 :             if (have_dp)
  945 dean.a.rasheed@gmail     6804                 :UBC           0 :                 goto invalid_syntax;
 2943 peter_e@gmx.net          6805                 :CBC        9104 :             have_dp = true;
 9363 tgl@sss.pgh.pa.us        6806                 :           9104 :             cp++;
                               6807                 :                :             /* decimal point must not be followed by underscore */
  945 dean.a.rasheed@gmail     6808         [ +  + ]:           9104 :             if (*cp == '_')
                               6809                 :              3 :                 goto invalid_syntax;
                               6810                 :                :         }
                               6811         [ +  + ]:            763 :         else if (*cp == '_')
                               6812                 :                :         {
                               6813                 :                :             /* underscore must be followed by more digits */
                               6814                 :             93 :             cp++;
                               6815         [ +  + ]:             93 :             if (!isdigit((unsigned char) *cp))
                               6816                 :              9 :                 goto invalid_syntax;
                               6817                 :                :         }
                               6818                 :                :         else
 9363 tgl@sss.pgh.pa.us        6819                 :            670 :             break;
                               6820                 :                :     }
                               6821                 :                : 
 8205                          6822                 :          92647 :     ddigits = i - DEC_DIGITS;
                               6823                 :                :     /* trailing padding for digit alignment later */
 8069 bruce@momjian.us         6824                 :          92647 :     memset(decdigits + i, 0, DEC_DIGITS - 1);
                               6825                 :                : 
                               6826                 :                :     /* Handle exponent, if any */
 9747 JanWieck@Yahoo.com       6827   [ +  +  +  + ]:          92647 :     if (*cp == 'e' || *cp == 'E')
                               6828                 :                :     {
  945 dean.a.rasheed@gmail     6829                 :            646 :         int64       exponent = 0;
                               6830                 :            646 :         bool        neg = false;
                               6831                 :                : 
                               6832                 :                :         /*
                               6833                 :                :          * At this point, dweight and dscale can't be more than about
                               6834                 :                :          * INT_MAX/2 due to the MaxAllocSize limit on string length, so
                               6835                 :                :          * constraining the exponent similarly should be enough to prevent
                               6836                 :                :          * integer overflow in this function.  If the value is too large to
                               6837                 :                :          * fit in storage format, make_result() will complain about it later;
                               6838                 :                :          * for consistency use the same ereport errcode/text as make_result().
                               6839                 :                :          */
                               6840                 :                : 
                               6841                 :                :         /* exponent sign */
                               6842                 :            646 :         cp++;
                               6843         [ +  + ]:            646 :         if (*cp == '+')
                               6844                 :             77 :             cp++;
                               6845         [ +  + ]:            569 :         else if (*cp == '-')
                               6846                 :                :         {
                               6847                 :            245 :             neg = true;
                               6848                 :            245 :             cp++;
                               6849                 :                :         }
                               6850                 :                : 
                               6851                 :                :         /* exponent digits */
                               6852         [ +  + ]:            646 :         if (!isdigit((unsigned char) *cp))
                               6853                 :              3 :             goto invalid_syntax;
                               6854                 :                : 
                               6855         [ +  + ]:           2272 :         while (*cp)
                               6856                 :                :         {
                               6857         [ +  + ]:           1638 :             if (isdigit((unsigned char) *cp))
                               6858                 :                :             {
                               6859                 :           1617 :                 exponent = exponent * 10 + (*cp++ - '0');
                               6860         [ +  + ]:           1617 :                 if (exponent > PG_INT32_MAX / 2)
                               6861                 :              3 :                     goto out_of_range;
                               6862                 :                :             }
                               6863         [ +  - ]:             21 :             else if (*cp == '_')
                               6864                 :                :             {
                               6865                 :                :                 /* underscore must be followed by more digits */
                               6866                 :             21 :                 cp++;
                               6867         [ +  + ]:             21 :                 if (!isdigit((unsigned char) *cp))
                               6868                 :              6 :                     goto invalid_syntax;
                               6869                 :                :             }
                               6870                 :                :             else
  945 dean.a.rasheed@gmail     6871                 :UBC           0 :                 break;
                               6872                 :                :         }
                               6873                 :                : 
  945 dean.a.rasheed@gmail     6874         [ +  + ]:CBC         634 :         if (neg)
                               6875                 :            245 :             exponent = -exponent;
                               6876                 :                : 
 8205 tgl@sss.pgh.pa.us        6877                 :            634 :         dweight += (int) exponent;
                               6878                 :            634 :         dscale -= (int) exponent;
                               6879         [ +  + ]:            634 :         if (dscale < 0)
                               6880                 :            287 :             dscale = 0;
                               6881                 :                :     }
                               6882                 :                : 
                               6883                 :                :     /*
                               6884                 :                :      * Okay, convert pure-decimal representation to base NBASE.  First we need
                               6885                 :                :      * to determine the converted weight and ndigits.  offset is the number of
                               6886                 :                :      * decimal zeroes to insert before the first given digit to have a
                               6887                 :                :      * correctly aligned first NBASE digit.
                               6888                 :                :      */
                               6889         [ +  + ]:          92635 :     if (dweight >= 0)
 8069 bruce@momjian.us         6890                 :          92250 :         weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
                               6891                 :                :     else
                               6892                 :            385 :         weight = -((-dweight - 1) / DEC_DIGITS + 1);
 8205 tgl@sss.pgh.pa.us        6893                 :          92635 :     offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
 8069 bruce@momjian.us         6894                 :          92635 :     ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
                               6895                 :                : 
 8205 tgl@sss.pgh.pa.us        6896                 :          92635 :     alloc_var(dest, ndigits);
                               6897                 :          92635 :     dest->sign = sign;
                               6898                 :          92635 :     dest->weight = weight;
                               6899                 :          92635 :     dest->dscale = dscale;
                               6900                 :                : 
                               6901                 :          92635 :     i = DEC_DIGITS - offset;
                               6902                 :          92635 :     digits = dest->digits;
                               6903                 :                : 
                               6904         [ +  + ]:         224502 :     while (ndigits-- > 0)
                               6905                 :                :     {
                               6906                 :                : #if DEC_DIGITS == 4
 8069 bruce@momjian.us         6907                 :         131867 :         *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
                               6908                 :         131867 :                      decdigits[i + 2]) * 10 + decdigits[i + 3];
                               6909                 :                : #elif DEC_DIGITS == 2
                               6910                 :                :         *digits++ = decdigits[i] * 10 + decdigits[i + 1];
                               6911                 :                : #elif DEC_DIGITS == 1
                               6912                 :                :         *digits++ = decdigits[i];
                               6913                 :                : #else
                               6914                 :                : #error unsupported NBASE
                               6915                 :                : #endif
 8205 tgl@sss.pgh.pa.us        6916                 :         131867 :         i += DEC_DIGITS;
                               6917                 :                :     }
                               6918                 :                : 
                               6919                 :          92635 :     pfree(decdigits);
                               6920                 :                : 
                               6921                 :                :     /* Strip any leading/trailing zeroes, and normalize weight if zero */
                               6922                 :          92635 :     strip_var(dest);
                               6923                 :                : 
                               6924                 :                :     /* Return end+1 position for caller */
 1002                          6925                 :          92635 :     *endptr = cp;
                               6926                 :                : 
                               6927                 :          92635 :     return true;
                               6928                 :                : 
  945 dean.a.rasheed@gmail     6929                 :              3 : out_of_range:
                               6930         [ +  - ]:              3 :     ereturn(escontext, false,
                               6931                 :                :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               6932                 :                :              errmsg("value overflows numeric format")));
                               6933                 :                : 
                               6934                 :             21 : invalid_syntax:
                               6935         [ +  - ]:             21 :     ereturn(escontext, false,
                               6936                 :                :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               6937                 :                :              errmsg("invalid input syntax for type %s: \"%s\"",
                               6938                 :                :                     "numeric", str)));
                               6939                 :                : }
                               6940                 :                : 
                               6941                 :                : 
                               6942                 :                : /*
                               6943                 :                :  * Return the numeric value of a single hex digit.
                               6944                 :                :  */
                               6945                 :                : static inline int
  957                          6946                 :            354 : xdigit_value(char dig)
                               6947                 :                : {
                               6948   [ +  -  +  + ]:            447 :     return dig >= '0' && dig <= '9' ? dig - '0' :
                               6949   [ +  +  +  - ]:            147 :         dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
                               6950   [ +  -  +  - ]:             54 :         dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
                               6951                 :                : }
                               6952                 :                : 
                               6953                 :                : /*
                               6954                 :                :  * set_var_from_non_decimal_integer_str()
                               6955                 :                :  *
                               6956                 :                :  *  Parse a string containing a non-decimal integer
                               6957                 :                :  *
                               6958                 :                :  * This function does not handle leading or trailing spaces.  It returns
                               6959                 :                :  * the end+1 position parsed into *endptr, so that caller can check for
                               6960                 :                :  * trailing spaces/garbage if deemed necessary.
                               6961                 :                :  *
                               6962                 :                :  * cp is the place to actually start parsing; str is what to use in error
                               6963                 :                :  * reports.  The number's sign and base prefix indicator (e.g., "0x") are
                               6964                 :                :  * assumed to have already been parsed, so cp should point to the number's
                               6965                 :                :  * first digit in the base specified.
                               6966                 :                :  *
                               6967                 :                :  * base is expected to be 2, 8 or 16.
                               6968                 :                :  *
                               6969                 :                :  * Returns true on success, false on failure (if escontext points to an
                               6970                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               6971                 :                :  */
                               6972                 :                : static bool
                               6973                 :             78 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
                               6974                 :                :                                      int base, NumericVar *dest,
                               6975                 :                :                                      const char **endptr, Node *escontext)
                               6976                 :                : {
                               6977                 :             78 :     const char *firstdigit = cp;
                               6978                 :                :     int64       tmp;
                               6979                 :                :     int64       mul;
                               6980                 :                :     NumericVar  tmp_var;
                               6981                 :                : 
                               6982                 :             78 :     init_var(&tmp_var);
                               6983                 :                : 
                               6984                 :             78 :     zero_var(dest);
                               6985                 :                : 
                               6986                 :                :     /*
                               6987                 :                :      * Process input digits in groups that fit in int64.  Here "tmp" is the
                               6988                 :                :      * value of the digits in the group, and "mul" is base^n, where n is the
                               6989                 :                :      * number of digits in the group.  Thus tmp < mul, and we must start a new
                               6990                 :                :      * group when mul * base threatens to overflow PG_INT64_MAX.
                               6991                 :                :      */
                               6992                 :             78 :     tmp = 0;
                               6993                 :             78 :     mul = 1;
                               6994                 :                : 
                               6995         [ +  + ]:             78 :     if (base == 16)
                               6996                 :                :     {
                               6997         [ +  + ]:            414 :         while (*cp)
                               6998                 :                :         {
                               6999         [ +  + ]:            399 :             if (isxdigit((unsigned char) *cp))
                               7000                 :                :             {
                               7001         [ +  + ]:            354 :                 if (mul > PG_INT64_MAX / 16)
                               7002                 :                :                 {
                               7003                 :                :                     /* Add the contribution from this group of digits */
                               7004                 :             15 :                     int64_to_numericvar(mul, &tmp_var);
                               7005                 :             15 :                     mul_var(dest, &tmp_var, dest, 0);
                               7006                 :             15 :                     int64_to_numericvar(tmp, &tmp_var);
                               7007                 :             15 :                     add_var(dest, &tmp_var, dest);
                               7008                 :                : 
                               7009                 :                :                     /* Result will overflow if weight overflows int16 */
  425                          7010         [ -  + ]:             15 :                     if (dest->weight > NUMERIC_WEIGHT_MAX)
  957 dean.a.rasheed@gmail     7011                 :UBC           0 :                         goto out_of_range;
                               7012                 :                : 
                               7013                 :                :                     /* Begin a new group */
  957 dean.a.rasheed@gmail     7014                 :CBC          15 :                     tmp = 0;
                               7015                 :             15 :                     mul = 1;
                               7016                 :                :                 }
                               7017                 :                : 
                               7018                 :            354 :                 tmp = tmp * 16 + xdigit_value(*cp++);
                               7019                 :            354 :                 mul = mul * 16;
                               7020                 :                :             }
  945                          7021         [ +  + ]:             45 :             else if (*cp == '_')
                               7022                 :                :             {
                               7023                 :                :                 /* Underscore must be followed by more digits */
                               7024                 :             33 :                 cp++;
                               7025         [ +  + ]:             33 :                 if (!isxdigit((unsigned char) *cp))
                               7026                 :              9 :                     goto invalid_syntax;
                               7027                 :                :             }
                               7028                 :                :             else
  957                          7029                 :             12 :                 break;
                               7030                 :                :         }
                               7031                 :                :     }
                               7032         [ +  + ]:             42 :     else if (base == 8)
                               7033                 :                :     {
                               7034         [ +  + ]:            318 :         while (*cp)
                               7035                 :                :         {
                               7036   [ +  +  +  + ]:            303 :             if (*cp >= '0' && *cp <= '7')
                               7037                 :                :             {
                               7038         [ +  + ]:            279 :                 if (mul > PG_INT64_MAX / 8)
                               7039                 :                :                 {
                               7040                 :                :                     /* Add the contribution from this group of digits */
                               7041                 :              9 :                     int64_to_numericvar(mul, &tmp_var);
                               7042                 :              9 :                     mul_var(dest, &tmp_var, dest, 0);
                               7043                 :              9 :                     int64_to_numericvar(tmp, &tmp_var);
                               7044                 :              9 :                     add_var(dest, &tmp_var, dest);
                               7045                 :                : 
                               7046                 :                :                     /* Result will overflow if weight overflows int16 */
  425                          7047         [ -  + ]:              9 :                     if (dest->weight > NUMERIC_WEIGHT_MAX)
  957 dean.a.rasheed@gmail     7048                 :UBC           0 :                         goto out_of_range;
                               7049                 :                : 
                               7050                 :                :                     /* Begin a new group */
  957 dean.a.rasheed@gmail     7051                 :CBC           9 :                     tmp = 0;
                               7052                 :              9 :                     mul = 1;
                               7053                 :                :                 }
                               7054                 :                : 
                               7055                 :            279 :                 tmp = tmp * 8 + (*cp++ - '0');
                               7056                 :            279 :                 mul = mul * 8;
                               7057                 :                :             }
  945                          7058         [ +  + ]:             24 :             else if (*cp == '_')
                               7059                 :                :             {
                               7060                 :                :                 /* Underscore must be followed by more digits */
                               7061                 :             18 :                 cp++;
                               7062   [ +  -  -  + ]:             18 :                 if (*cp < '0' || *cp > '7')
  945 dean.a.rasheed@gmail     7063                 :UBC           0 :                     goto invalid_syntax;
                               7064                 :                :             }
                               7065                 :                :             else
  957 dean.a.rasheed@gmail     7066                 :CBC           6 :                 break;
                               7067                 :                :         }
                               7068                 :                :     }
                               7069         [ +  - ]:             21 :     else if (base == 2)
                               7070                 :                :     {
                               7071         [ +  + ]:            780 :         while (*cp)
                               7072                 :                :         {
                               7073   [ +  +  +  + ]:            765 :             if (*cp >= '0' && *cp <= '1')
                               7074                 :                :             {
                               7075         [ +  + ]:            708 :                 if (mul > PG_INT64_MAX / 2)
                               7076                 :                :                 {
                               7077                 :                :                     /* Add the contribution from this group of digits */
                               7078                 :              9 :                     int64_to_numericvar(mul, &tmp_var);
                               7079                 :              9 :                     mul_var(dest, &tmp_var, dest, 0);
                               7080                 :              9 :                     int64_to_numericvar(tmp, &tmp_var);
                               7081                 :              9 :                     add_var(dest, &tmp_var, dest);
                               7082                 :                : 
                               7083                 :                :                     /* Result will overflow if weight overflows int16 */
  425                          7084         [ -  + ]:              9 :                     if (dest->weight > NUMERIC_WEIGHT_MAX)
  957 dean.a.rasheed@gmail     7085                 :UBC           0 :                         goto out_of_range;
                               7086                 :                : 
                               7087                 :                :                     /* Begin a new group */
  957 dean.a.rasheed@gmail     7088                 :CBC           9 :                     tmp = 0;
                               7089                 :              9 :                     mul = 1;
                               7090                 :                :                 }
                               7091                 :                : 
                               7092                 :            708 :                 tmp = tmp * 2 + (*cp++ - '0');
                               7093                 :            708 :                 mul = mul * 2;
                               7094                 :                :             }
  945                          7095         [ +  + ]:             57 :             else if (*cp == '_')
                               7096                 :                :             {
                               7097                 :                :                 /* Underscore must be followed by more digits */
                               7098                 :             51 :                 cp++;
                               7099   [ +  -  -  + ]:             51 :                 if (*cp < '0' || *cp > '1')
  945 dean.a.rasheed@gmail     7100                 :UBC           0 :                     goto invalid_syntax;
                               7101                 :                :             }
                               7102                 :                :             else
  957 dean.a.rasheed@gmail     7103                 :CBC           6 :                 break;
                               7104                 :                :         }
                               7105                 :                :     }
                               7106                 :                :     else
                               7107                 :                :         /* Should never happen; treat as invalid input */
  957 dean.a.rasheed@gmail     7108                 :UBC           0 :         goto invalid_syntax;
                               7109                 :                : 
                               7110                 :                :     /* Check that we got at least one digit */
  957 dean.a.rasheed@gmail     7111         [ -  + ]:CBC          69 :     if (unlikely(cp == firstdigit))
  957 dean.a.rasheed@gmail     7112                 :UBC           0 :         goto invalid_syntax;
                               7113                 :                : 
                               7114                 :                :     /* Add the contribution from the final group of digits */
  957 dean.a.rasheed@gmail     7115                 :CBC          69 :     int64_to_numericvar(mul, &tmp_var);
                               7116                 :             69 :     mul_var(dest, &tmp_var, dest, 0);
                               7117                 :             69 :     int64_to_numericvar(tmp, &tmp_var);
                               7118                 :             69 :     add_var(dest, &tmp_var, dest);
                               7119                 :                : 
  425                          7120         [ -  + ]:             69 :     if (dest->weight > NUMERIC_WEIGHT_MAX)
  957 dean.a.rasheed@gmail     7121                 :UBC           0 :         goto out_of_range;
                               7122                 :                : 
  957 dean.a.rasheed@gmail     7123                 :CBC          69 :     dest->sign = sign;
                               7124                 :                : 
                               7125                 :             69 :     free_var(&tmp_var);
                               7126                 :                : 
                               7127                 :                :     /* Return end+1 position for caller */
                               7128                 :             69 :     *endptr = cp;
                               7129                 :                : 
                               7130                 :             69 :     return true;
                               7131                 :                : 
  957 dean.a.rasheed@gmail     7132                 :UBC           0 : out_of_range:
                               7133         [ #  # ]:              0 :     ereturn(escontext, false,
                               7134                 :                :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7135                 :                :              errmsg("value overflows numeric format")));
                               7136                 :                : 
  957 dean.a.rasheed@gmail     7137                 :CBC           9 : invalid_syntax:
                               7138         [ +  - ]:              9 :     ereturn(escontext, false,
                               7139                 :                :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               7140                 :                :              errmsg("invalid input syntax for type %s: \"%s\"",
                               7141                 :                :                     "numeric", str)));
                               7142                 :                : }
                               7143                 :                : 
                               7144                 :                : 
                               7145                 :                : /*
                               7146                 :                :  * set_var_from_num() -
                               7147                 :                :  *
                               7148                 :                :  *  Convert the packed db format into a variable
                               7149                 :                :  */
                               7150                 :                : static void
 9601 bruce@momjian.us         7151                 :           6464 : set_var_from_num(Numeric num, NumericVar *dest)
                               7152                 :                : {
                               7153                 :                :     int         ndigits;
                               7154                 :                : 
 7151                          7155         [ +  + ]:           6464 :     ndigits = NUMERIC_NDIGITS(num);
                               7156                 :                : 
 8205 tgl@sss.pgh.pa.us        7157                 :           6464 :     alloc_var(dest, ndigits);
                               7158                 :                : 
 5513 rhaas@postgresql.org     7159   [ +  +  +  + ]:           6464 :     dest->weight = NUMERIC_WEIGHT(num);
 9601 bruce@momjian.us         7160   [ +  +  -  + ]:           6464 :     dest->sign = NUMERIC_SIGN(num);
 8205 tgl@sss.pgh.pa.us        7161         [ +  + ]:           6464 :     dest->dscale = NUMERIC_DSCALE(num);
                               7162                 :                : 
 5513 rhaas@postgresql.org     7163         [ +  + ]:           6464 :     memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
 9747 JanWieck@Yahoo.com       7164                 :           6464 : }
                               7165                 :                : 
                               7166                 :                : 
                               7167                 :                : /*
                               7168                 :                :  * init_var_from_num() -
                               7169                 :                :  *
                               7170                 :                :  *  Initialize a variable from packed db format. The digits array is not
                               7171                 :                :  *  copied, which saves some cycles when the resulting var is not modified.
                               7172                 :                :  *  Also, there's no need to call free_var(), as long as you don't assign any
                               7173                 :                :  *  other value to it (with set_var_* functions, or by using the var as the
                               7174                 :                :  *  destination of a function like add_var())
                               7175                 :                :  *
                               7176                 :                :  *  CAUTION: Do not modify the digits buffer of a var initialized with this
                               7177                 :                :  *  function, e.g by calling round_var() or trunc_var(), as the changes will
                               7178                 :                :  *  propagate to the original Numeric! It's OK to use it as the destination
                               7179                 :                :  *  argument of one of the calculational functions, though.
                               7180                 :                :  */
                               7181                 :                : static void
 4672 heikki.linnakangas@i     7182                 :        2932712 : init_var_from_num(Numeric num, NumericVar *dest)
                               7183                 :                : {
                               7184         [ +  + ]:        2932712 :     dest->ndigits = NUMERIC_NDIGITS(num);
                               7185   [ +  +  +  + ]:        2932712 :     dest->weight = NUMERIC_WEIGHT(num);
                               7186   [ +  +  -  + ]:        2932712 :     dest->sign = NUMERIC_SIGN(num);
                               7187         [ +  + ]:        2932712 :     dest->dscale = NUMERIC_DSCALE(num);
                               7188         [ +  + ]:        2932712 :     dest->digits = NUMERIC_DIGITS(num);
 4483 bruce@momjian.us         7189                 :        2932712 :     dest->buf = NULL;            /* digits array is not palloc'd */
 4672 heikki.linnakangas@i     7190                 :        2932712 : }
                               7191                 :                : 
                               7192                 :                : 
                               7193                 :                : /*
                               7194                 :                :  * set_var_from_var() -
                               7195                 :                :  *
                               7196                 :                :  *  Copy one variable into another
                               7197                 :                :  */
                               7198                 :                : static void
 2918 andres@anarazel.de       7199                 :          17597 : set_var_from_var(const NumericVar *value, NumericVar *dest)
                               7200                 :                : {
                               7201                 :                :     NumericDigit *newbuf;
                               7202                 :                : 
 9363 tgl@sss.pgh.pa.us        7203                 :          17597 :     newbuf = digitbuf_alloc(value->ndigits + 1);
                               7204                 :          17597 :     newbuf[0] = 0;              /* spare digit for rounding */
 3688                          7205         [ +  + ]:          17597 :     if (value->ndigits > 0)       /* else value->digits might be null */
                               7206                 :          17126 :         memcpy(newbuf + 1, value->digits,
                               7207                 :          17126 :                value->ndigits * sizeof(NumericDigit));
                               7208                 :                : 
 9747 JanWieck@Yahoo.com       7209         [ +  + ]:          17597 :     digitbuf_free(dest->buf);
                               7210                 :                : 
 7885 neilc@samurai.com        7211                 :          17597 :     memmove(dest, value, sizeof(NumericVar));
 9601 bruce@momjian.us         7212                 :          17597 :     dest->buf = newbuf;
 9363 tgl@sss.pgh.pa.us        7213                 :          17597 :     dest->digits = newbuf + 1;
                               7214                 :          17597 : }
                               7215                 :                : 
                               7216                 :                : 
                               7217                 :                : /*
                               7218                 :                :  * get_str_from_var() -
                               7219                 :                :  *
                               7220                 :                :  *  Convert a var to text representation (guts of numeric_out).
                               7221                 :                :  *  The var is displayed to the number of digits indicated by its dscale.
                               7222                 :                :  *  Returns a palloc'd string.
                               7223                 :                :  */
                               7224                 :                : static char *
 2918 andres@anarazel.de       7225                 :         444083 : get_str_from_var(const NumericVar *var)
                               7226                 :                : {
                               7227                 :                :     int         dscale;
                               7228                 :                :     char       *str;
                               7229                 :                :     char       *cp;
                               7230                 :                :     char       *endcp;
                               7231                 :                :     int         i;
                               7232                 :                :     int         d;
                               7233                 :                :     NumericDigit dig;
                               7234                 :                : 
                               7235                 :                : #if DEC_DIGITS > 1
                               7236                 :                :     NumericDigit d1;
                               7237                 :                : #endif
                               7238                 :                : 
 4672 heikki.linnakangas@i     7239                 :         444083 :     dscale = var->dscale;
                               7240                 :                : 
                               7241                 :                :     /*
                               7242                 :                :      * Allocate space for the result.
                               7243                 :                :      *
                               7244                 :                :      * i is set to the # of decimal digits before decimal point. dscale is the
                               7245                 :                :      * # of decimal digits we will print after decimal point. We may generate
                               7246                 :                :      * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
                               7247                 :                :      * need room for sign, decimal point, null terminator.
                               7248                 :                :      */
 8205 tgl@sss.pgh.pa.us        7249                 :         444083 :     i = (var->weight + 1) * DEC_DIGITS;
                               7250         [ +  + ]:         444083 :     if (i <= 0)
                               7251                 :          68829 :         i = 1;
                               7252                 :                : 
                               7253                 :         444083 :     str = palloc(i + dscale + DEC_DIGITS + 2);
 9363                          7254                 :         444083 :     cp = str;
                               7255                 :                : 
                               7256                 :                :     /*
                               7257                 :                :      * Output a dash for negative values
                               7258                 :                :      */
                               7259         [ +  + ]:         444083 :     if (var->sign == NUMERIC_NEG)
                               7260                 :           3475 :         *cp++ = '-';
                               7261                 :                : 
                               7262                 :                :     /*
                               7263                 :                :      * Output all digits before the decimal point
                               7264                 :                :      */
 8205                          7265         [ +  + ]:         444083 :     if (var->weight < 0)
                               7266                 :                :     {
                               7267                 :          68829 :         d = var->weight + 1;
                               7268                 :          68829 :         *cp++ = '0';
                               7269                 :                :     }
                               7270                 :                :     else
                               7271                 :                :     {
                               7272         [ +  + ]:         804446 :         for (d = 0; d <= var->weight; d++)
                               7273                 :                :         {
                               7274         [ +  + ]:         429192 :             dig = (d < var->ndigits) ? var->digits[d] : 0;
                               7275                 :                :             /* In the first digit, suppress extra leading decimal zeroes */
                               7276                 :                : #if DEC_DIGITS == 4
                               7277                 :                :             {
 8069 bruce@momjian.us         7278                 :         429192 :                 bool        putit = (d > 0);
                               7279                 :                : 
 8205 tgl@sss.pgh.pa.us        7280                 :         429192 :                 d1 = dig / 1000;
                               7281                 :         429192 :                 dig -= d1 * 1000;
                               7282                 :         429192 :                 putit |= (d1 > 0);
                               7283         [ +  + ]:         429192 :                 if (putit)
                               7284                 :          84922 :                     *cp++ = d1 + '0';
                               7285                 :         429192 :                 d1 = dig / 100;
                               7286                 :         429192 :                 dig -= d1 * 100;
                               7287                 :         429192 :                 putit |= (d1 > 0);
                               7288         [ +  + ]:         429192 :                 if (putit)
                               7289                 :         290539 :                     *cp++ = d1 + '0';
                               7290                 :         429192 :                 d1 = dig / 10;
                               7291                 :         429192 :                 dig -= d1 * 10;
                               7292                 :         429192 :                 putit |= (d1 > 0);
                               7293         [ +  + ]:         429192 :                 if (putit)
                               7294                 :         357184 :                     *cp++ = d1 + '0';
                               7295                 :         429192 :                 *cp++ = dig + '0';
                               7296                 :                :             }
                               7297                 :                : #elif DEC_DIGITS == 2
                               7298                 :                :             d1 = dig / 10;
                               7299                 :                :             dig -= d1 * 10;
                               7300                 :                :             if (d1 > 0 || d > 0)
                               7301                 :                :                 *cp++ = d1 + '0';
                               7302                 :                :             *cp++ = dig + '0';
                               7303                 :                : #elif DEC_DIGITS == 1
                               7304                 :                :             *cp++ = dig + '0';
                               7305                 :                : #else
                               7306                 :                : #error unsupported NBASE
                               7307                 :                : #endif
                               7308                 :                :         }
                               7309                 :                :     }
                               7310                 :                : 
                               7311                 :                :     /*
                               7312                 :                :      * If requested, output a decimal point and all the digits that follow it.
                               7313                 :                :      * We initially put out a multiple of DEC_DIGITS digits, then truncate if
                               7314                 :                :      * needed.
                               7315                 :                :      */
 9363                          7316         [ +  + ]:         444083 :     if (dscale > 0)
                               7317                 :                :     {
                               7318                 :         322519 :         *cp++ = '.';
 8205                          7319                 :         322519 :         endcp = cp + dscale;
                               7320         [ +  + ]:         952469 :         for (i = 0; i < dscale; d++, i += DEC_DIGITS)
                               7321                 :                :         {
                               7322   [ +  +  +  + ]:         629950 :             dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
                               7323                 :                : #if DEC_DIGITS == 4
                               7324                 :         629950 :             d1 = dig / 1000;
                               7325                 :         629950 :             dig -= d1 * 1000;
                               7326                 :         629950 :             *cp++ = d1 + '0';
                               7327                 :         629950 :             d1 = dig / 100;
                               7328                 :         629950 :             dig -= d1 * 100;
                               7329                 :         629950 :             *cp++ = d1 + '0';
                               7330                 :         629950 :             d1 = dig / 10;
                               7331                 :         629950 :             dig -= d1 * 10;
                               7332                 :         629950 :             *cp++ = d1 + '0';
                               7333                 :         629950 :             *cp++ = dig + '0';
                               7334                 :                : #elif DEC_DIGITS == 2
                               7335                 :                :             d1 = dig / 10;
                               7336                 :                :             dig -= d1 * 10;
                               7337                 :                :             *cp++ = d1 + '0';
                               7338                 :                :             *cp++ = dig + '0';
                               7339                 :                : #elif DEC_DIGITS == 1
                               7340                 :                :             *cp++ = dig + '0';
                               7341                 :                : #else
                               7342                 :                : #error unsupported NBASE
                               7343                 :                : #endif
                               7344                 :                :         }
                               7345                 :         322519 :         cp = endcp;
                               7346                 :                :     }
                               7347                 :                : 
                               7348                 :                :     /*
                               7349                 :                :      * terminate the string and return it
                               7350                 :                :      */
 9363                          7351                 :         444083 :     *cp = '\0';
                               7352                 :         444083 :     return str;
                               7353                 :                : }
                               7354                 :                : 
                               7355                 :                : /*
                               7356                 :                :  * get_str_from_var_sci() -
                               7357                 :                :  *
                               7358                 :                :  *  Convert a var to a normalised scientific notation text representation.
                               7359                 :                :  *  This function does the heavy lifting for numeric_out_sci().
                               7360                 :                :  *
                               7361                 :                :  *  This notation has the general form a * 10^b, where a is known as the
                               7362                 :                :  *  "significand" and b is known as the "exponent".
                               7363                 :                :  *
                               7364                 :                :  *  Because we can't do superscript in ASCII (and because we want to copy
                               7365                 :                :  *  printf's behaviour) we display the exponent using E notation, with a
                               7366                 :                :  *  minimum of two exponent digits.
                               7367                 :                :  *
                               7368                 :                :  *  For example, the value 1234 could be output as 1.2e+03.
                               7369                 :                :  *
                               7370                 :                :  *  We assume that the exponent can fit into an int32.
                               7371                 :                :  *
                               7372                 :                :  *  rscale is the number of decimal digits desired after the decimal point in
                               7373                 :                :  *  the output, negative values will be treated as meaning zero.
                               7374                 :                :  *
                               7375                 :                :  *  Returns a palloc'd string.
                               7376                 :                :  */
                               7377                 :                : static char *
 2918 andres@anarazel.de       7378                 :            114 : get_str_from_var_sci(const NumericVar *var, int rscale)
                               7379                 :                : {
                               7380                 :                :     int32       exponent;
                               7381                 :                :     NumericVar  tmp_var;
                               7382                 :                :     size_t      len;
                               7383                 :                :     char       *str;
                               7384                 :                :     char       *sig_out;
                               7385                 :                : 
 5871 tgl@sss.pgh.pa.us        7386         [ -  + ]:            114 :     if (rscale < 0)
 5871 tgl@sss.pgh.pa.us        7387                 :UBC           0 :         rscale = 0;
                               7388                 :                : 
                               7389                 :                :     /*
                               7390                 :                :      * Determine the exponent of this number in normalised form.
                               7391                 :                :      *
                               7392                 :                :      * This is the exponent required to represent the number with only one
                               7393                 :                :      * significant digit before the decimal place.
                               7394                 :                :      */
 5871 tgl@sss.pgh.pa.us        7395         [ +  + ]:CBC         114 :     if (var->ndigits > 0)
                               7396                 :                :     {
                               7397                 :            105 :         exponent = (var->weight + 1) * DEC_DIGITS;
                               7398                 :                : 
                               7399                 :                :         /*
                               7400                 :                :          * Compensate for leading decimal zeroes in the first numeric digit by
                               7401                 :                :          * decrementing the exponent.
                               7402                 :                :          */
                               7403                 :            105 :         exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
                               7404                 :                :     }
                               7405                 :                :     else
                               7406                 :                :     {
                               7407                 :                :         /*
                               7408                 :                :          * If var has no digits, then it must be zero.
                               7409                 :                :          *
                               7410                 :                :          * Zero doesn't technically have a meaningful exponent in normalised
                               7411                 :                :          * notation, but we just display the exponent as zero for consistency
                               7412                 :                :          * of output.
                               7413                 :                :          */
                               7414                 :              9 :         exponent = 0;
                               7415                 :                :     }
                               7416                 :                : 
                               7417                 :                :     /*
                               7418                 :                :      * Divide var by 10^exponent to get the significand, rounding to rscale
                               7419                 :                :      * decimal digits in the process.
                               7420                 :                :      */
 1493 dean.a.rasheed@gmail     7421                 :            114 :     init_var(&tmp_var);
                               7422                 :                : 
                               7423                 :            114 :     power_ten_int(exponent, &tmp_var);
  337                          7424                 :            114 :     div_var(var, &tmp_var, &tmp_var, rscale, true, true);
 1493                          7425                 :            114 :     sig_out = get_str_from_var(&tmp_var);
                               7426                 :                : 
                               7427                 :            114 :     free_var(&tmp_var);
                               7428                 :                : 
                               7429                 :                :     /*
                               7430                 :                :      * Allocate space for the result.
                               7431                 :                :      *
                               7432                 :                :      * In addition to the significand, we need room for the exponent
                               7433                 :                :      * decoration ("e"), the sign of the exponent, up to 10 digits for the
                               7434                 :                :      * exponent itself, and of course the null terminator.
                               7435                 :                :      */
 5871 tgl@sss.pgh.pa.us        7436                 :            114 :     len = strlen(sig_out) + 13;
                               7437                 :            114 :     str = palloc(len);
                               7438                 :            114 :     snprintf(str, len, "%se%+03d", sig_out, exponent);
                               7439                 :                : 
                               7440                 :            114 :     pfree(sig_out);
                               7441                 :                : 
                               7442                 :            114 :     return str;
                               7443                 :                : }
                               7444                 :                : 
                               7445                 :                : 
                               7446                 :                : /*
                               7447                 :                :  * numericvar_serialize - serialize NumericVar to binary format
                               7448                 :                :  *
                               7449                 :                :  * At variable level, no checks are performed on the weight or dscale, allowing
                               7450                 :                :  * us to pass around intermediate values with higher precision than supported
                               7451                 :                :  * by the numeric type.  Note: this is incompatible with numeric_send/recv(),
                               7452                 :                :  * which use 16-bit integers for these fields.
                               7453                 :                :  */
                               7454                 :                : static void
 1524 dean.a.rasheed@gmail     7455                 :             48 : numericvar_serialize(StringInfo buf, const NumericVar *var)
                               7456                 :                : {
                               7457                 :                :     int         i;
                               7458                 :                : 
                               7459                 :             48 :     pq_sendint32(buf, var->ndigits);
                               7460                 :             48 :     pq_sendint32(buf, var->weight);
                               7461                 :             48 :     pq_sendint32(buf, var->sign);
                               7462                 :             48 :     pq_sendint32(buf, var->dscale);
                               7463         [ +  + ]:         318879 :     for (i = 0; i < var->ndigits; i++)
                               7464                 :         318831 :         pq_sendint16(buf, var->digits[i]);
                               7465                 :             48 : }
                               7466                 :                : 
                               7467                 :                : /*
                               7468                 :                :  * numericvar_deserialize - deserialize binary format to NumericVar
                               7469                 :                :  */
                               7470                 :                : static void
                               7471                 :             48 : numericvar_deserialize(StringInfo buf, NumericVar *var)
                               7472                 :                : {
                               7473                 :                :     int         len,
                               7474                 :                :                 i;
                               7475                 :                : 
                               7476                 :             48 :     len = pq_getmsgint(buf, sizeof(int32));
                               7477                 :                : 
                               7478                 :             48 :     alloc_var(var, len);        /* sets var->ndigits */
                               7479                 :                : 
                               7480                 :             48 :     var->weight = pq_getmsgint(buf, sizeof(int32));
                               7481                 :             48 :     var->sign = pq_getmsgint(buf, sizeof(int32));
                               7482                 :             48 :     var->dscale = pq_getmsgint(buf, sizeof(int32));
                               7483         [ +  + ]:         318879 :     for (i = 0; i < len; i++)
                               7484                 :         318831 :         var->digits[i] = pq_getmsgint(buf, sizeof(int16));
                               7485                 :             48 : }
                               7486                 :                : 
                               7487                 :                : 
                               7488                 :                : /*
                               7489                 :                :  * duplicate_numeric() - copy a packed-format Numeric
                               7490                 :                :  *
                               7491                 :                :  * This will handle NaN and Infinity cases.
                               7492                 :                :  */
                               7493                 :                : static Numeric
 1872 tgl@sss.pgh.pa.us        7494                 :          14246 : duplicate_numeric(Numeric num)
                               7495                 :                : {
                               7496                 :                :     Numeric     res;
                               7497                 :                : 
                               7498                 :          14246 :     res = (Numeric) palloc(VARSIZE(num));
                               7499                 :          14246 :     memcpy(res, num, VARSIZE(num));
                               7500                 :          14246 :     return res;
                               7501                 :                : }
                               7502                 :                : 
                               7503                 :                : /*
                               7504                 :                :  * make_result_safe() -
                               7505                 :                :  *
                               7506                 :                :  *  Create the packed db numeric format in palloc()'d memory from
                               7507                 :                :  *  a variable.  This will handle NaN and Infinity cases.
                               7508                 :                :  */
                               7509                 :                : static Numeric
    1 michael@paquier.xyz      7510                 :GNC     1904608 : make_result_safe(const NumericVar *var, Node *escontext)
                               7511                 :                : {
                               7512                 :                :     Numeric     result;
 8205 tgl@sss.pgh.pa.us        7513                 :CBC     1904608 :     NumericDigit *digits = var->digits;
 9601 bruce@momjian.us         7514                 :        1904608 :     int         weight = var->weight;
                               7515                 :        1904608 :     int         sign = var->sign;
                               7516                 :                :     int         n;
                               7517                 :                :     Size        len;
                               7518                 :                : 
 1872 tgl@sss.pgh.pa.us        7519         [ +  + ]:        1904608 :     if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
                               7520                 :                :     {
                               7521                 :                :         /*
                               7522                 :                :          * Verify valid special value.  This could be just an Assert, perhaps,
                               7523                 :                :          * but it seems worthwhile to expend a few cycles to ensure that we
                               7524                 :                :          * never write any nonzero reserved bits to disk.
                               7525                 :                :          */
                               7526   [ +  +  +  +  :           1637 :         if (!(sign == NUMERIC_NAN ||
                                              -  + ]
                               7527                 :                :               sign == NUMERIC_PINF ||
                               7528                 :                :               sign == NUMERIC_NINF))
 1872 tgl@sss.pgh.pa.us        7529         [ #  # ]:UBC           0 :             elog(ERROR, "invalid numeric sign value 0x%x", sign);
                               7530                 :                : 
 5513 rhaas@postgresql.org     7531                 :CBC        1637 :         result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
                               7532                 :                : 
                               7533                 :           1637 :         SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
 1872 tgl@sss.pgh.pa.us        7534                 :           1637 :         result->choice.n_header = sign;
                               7535                 :                :         /* the header word is all we need */
                               7536                 :                : 
                               7537                 :                :         dump_numeric("make_result()", result);
 9747 JanWieck@Yahoo.com       7538                 :           1637 :         return result;
                               7539                 :                :     }
                               7540                 :                : 
 8205 tgl@sss.pgh.pa.us        7541                 :        1902971 :     n = var->ndigits;
                               7542                 :                : 
                               7543                 :                :     /* truncate leading zeroes */
                               7544   [ +  +  +  + ]:        1902989 :     while (n > 0 && *digits == 0)
                               7545                 :                :     {
                               7546                 :             18 :         digits++;
 9747 JanWieck@Yahoo.com       7547                 :             18 :         weight--;
                               7548                 :             18 :         n--;
                               7549                 :                :     }
                               7550                 :                :     /* truncate trailing zeroes */
 8205 tgl@sss.pgh.pa.us        7551   [ +  +  +  + ]:        1945639 :     while (n > 0 && digits[n - 1] == 0)
 9747 JanWieck@Yahoo.com       7552                 :          42668 :         n--;
                               7553                 :                : 
                               7554                 :                :     /* If zero result, force to weight=0 and positive sign */
                               7555         [ +  + ]:        1902971 :     if (n == 0)
                               7556                 :                :     {
                               7557                 :          65854 :         weight = 0;
 9601 bruce@momjian.us         7558                 :          65854 :         sign = NUMERIC_POS;
                               7559                 :                :     }
                               7560                 :                : 
                               7561                 :                :     /* Build the result */
 5513 rhaas@postgresql.org     7562   [ +  +  +  +  :        1902971 :     if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
                                              +  - ]
                               7563                 :                :     {
                               7564                 :        1902004 :         len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
                               7565                 :        1902004 :         result = (Numeric) palloc(len);
                               7566                 :        1902004 :         SET_VARSIZE(result, len);
 5401 peter_e@gmx.net          7567                 :        1902004 :         result->choice.n_short.n_header =
                               7568                 :                :             (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
                               7569                 :                :              : NUMERIC_SHORT)
 5513 rhaas@postgresql.org     7570         [ +  + ]:        1902004 :             | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
                               7571                 :        1902004 :             | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
                               7572                 :        1902004 :             | (weight & NUMERIC_SHORT_WEIGHT_MASK);
                               7573                 :                :     }
                               7574                 :                :     else
                               7575                 :                :     {
                               7576                 :            967 :         len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
                               7577                 :            967 :         result = (Numeric) palloc(len);
                               7578                 :            967 :         SET_VARSIZE(result, len);
                               7579                 :            967 :         result->choice.n_long.n_sign_dscale =
                               7580                 :            967 :             sign | (var->dscale & NUMERIC_DSCALE_MASK);
                               7581                 :            967 :         result->choice.n_long.n_weight = weight;
                               7582                 :                :     }
                               7583                 :                : 
                               7584   [ +  +  -  + ]:        1902971 :     Assert(NUMERIC_NDIGITS(result) == n);
 3688 tgl@sss.pgh.pa.us        7585         [ +  + ]:        1902971 :     if (n > 0)
                               7586         [ +  + ]:        1837117 :         memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
                               7587                 :                : 
                               7588                 :                :     /* Check for overflow of int16 fields */
 5513 rhaas@postgresql.org     7589   [ +  +  +  +  :        1902971 :     if (NUMERIC_WEIGHT(result) != weight ||
                                              +  + ]
 8205 tgl@sss.pgh.pa.us        7590   [ +  +  -  + ]:        1902956 :         NUMERIC_DSCALE(result) != var->dscale)
    1 michael@paquier.xyz      7591         [ +  + ]:GNC          15 :         ereturn(escontext, NULL,
                               7592                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7593                 :                :                  errmsg("value overflows numeric format")));
                               7594                 :                : 
                               7595                 :                :     dump_numeric("make_result()", result);
 9747 JanWieck@Yahoo.com       7596                 :CBC     1902956 :     return result;
                               7597                 :                : }
                               7598                 :                : 
                               7599                 :                : 
                               7600                 :                : /*
                               7601                 :                :  * make_result() -
                               7602                 :                :  *
                               7603                 :                :  *  An interface to make_result_safe() without "escontext" argument.
                               7604                 :                :  */
                               7605                 :                : static Numeric
 2366 akorotkov@postgresql     7606                 :        1133709 : make_result(const NumericVar *var)
                               7607                 :                : {
    1 michael@paquier.xyz      7608                 :GNC     1133709 :     return make_result_safe(var, NULL);
                               7609                 :                : }
                               7610                 :                : 
                               7611                 :                : 
                               7612                 :                : /*
                               7613                 :                :  * apply_typmod() -
                               7614                 :                :  *
                               7615                 :                :  *  Do bounds checking and rounding according to the specified typmod.
                               7616                 :                :  *  Note that this is only applied to normal finite values.
                               7617                 :                :  *
                               7618                 :                :  * Returns true on success, false on failure (if escontext points to an
                               7619                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               7620                 :                :  */
                               7621                 :                : static bool
 1002 tgl@sss.pgh.pa.us        7622                 :CBC       83208 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
                               7623                 :                : {
                               7624                 :                :     int         precision;
                               7625                 :                :     int         scale;
                               7626                 :                :     int         maxdigits;
                               7627                 :                :     int         ddigits;
                               7628                 :                :     int         i;
                               7629                 :                : 
                               7630                 :                :     /* Do nothing if we have an invalid typmod */
 1503 dean.a.rasheed@gmail     7631         [ +  + ]:          83208 :     if (!is_valid_numeric_typmod(typmod))
 1002 tgl@sss.pgh.pa.us        7632                 :          68635 :         return true;
                               7633                 :                : 
 1503 dean.a.rasheed@gmail     7634                 :          14573 :     precision = numeric_typmod_precision(typmod);
                               7635                 :          14573 :     scale = numeric_typmod_scale(typmod);
 8205 tgl@sss.pgh.pa.us        7636                 :          14573 :     maxdigits = precision - scale;
                               7637                 :                : 
                               7638                 :                :     /* Round to target scale (and set var->dscale) */
                               7639                 :          14573 :     round_var(var, scale);
                               7640                 :                : 
                               7641                 :                :     /* but don't allow var->dscale to be negative */
 1503 dean.a.rasheed@gmail     7642         [ +  + ]:          14573 :     if (var->dscale < 0)
                               7643                 :             63 :         var->dscale = 0;
                               7644                 :                : 
                               7645                 :                :     /*
                               7646                 :                :      * Check for overflow - note we can't do this before rounding, because
                               7647                 :                :      * rounding could raise the weight.  Also note that the var's weight could
                               7648                 :                :      * be inflated by leading zeroes, which will be stripped before storage
                               7649                 :                :      * but perhaps might not have been yet. In any case, we must recognize a
                               7650                 :                :      * true zero, whose weight doesn't mean anything.
                               7651                 :                :      */
 8205 tgl@sss.pgh.pa.us        7652                 :          14573 :     ddigits = (var->weight + 1) * DEC_DIGITS;
                               7653         [ +  + ]:          14573 :     if (ddigits > maxdigits)
                               7654                 :                :     {
                               7655                 :                :         /* Determine true weight; and check for all-zero result */
 9366                          7656         [ +  + ]:           3200 :         for (i = 0; i < var->ndigits; i++)
                               7657                 :                :         {
 8205                          7658                 :           3193 :             NumericDigit dig = var->digits[i];
                               7659                 :                : 
                               7660         [ +  - ]:           3193 :             if (dig)
                               7661                 :                :             {
                               7662                 :                :                 /* Adjust for any high-order decimal zero digits */
                               7663                 :                : #if DEC_DIGITS == 4
                               7664         [ +  + ]:           3193 :                 if (dig < 10)
                               7665                 :            144 :                     ddigits -= 3;
                               7666         [ +  + ]:           3049 :                 else if (dig < 100)
                               7667                 :            312 :                     ddigits -= 2;
                               7668         [ +  + ]:           2737 :                 else if (dig < 1000)
                               7669                 :           2728 :                     ddigits -= 1;
                               7670                 :                : #elif DEC_DIGITS == 2
                               7671                 :                :                 if (dig < 10)
                               7672                 :                :                     ddigits -= 1;
                               7673                 :                : #elif DEC_DIGITS == 1
                               7674                 :                :                 /* no adjustment */
                               7675                 :                : #else
                               7676                 :                : #error unsupported NBASE
                               7677                 :                : #endif
                               7678         [ +  + ]:           3193 :                 if (ddigits > maxdigits)
 1002                          7679   [ +  +  +  +  :             42 :                     ereturn(escontext, false,
                                              +  + ]
                               7680                 :                :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7681                 :                :                              errmsg("numeric field overflow"),
                               7682                 :                :                              errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
                               7683                 :                :                                        precision, scale,
                               7684                 :                :                     /* Display 10^0 as 1 */
                               7685                 :                :                                        maxdigits ? "10^" : "",
                               7686                 :                :                                        maxdigits ? maxdigits : 1
                               7687                 :                :                                        )));
 9366                          7688                 :           3151 :                 break;
                               7689                 :                :             }
 8205 tgl@sss.pgh.pa.us        7690                 :UBC           0 :             ddigits -= DEC_DIGITS;
                               7691                 :                :         }
                               7692                 :                :     }
                               7693                 :                : 
 1002 tgl@sss.pgh.pa.us        7694                 :CBC       14531 :     return true;
                               7695                 :                : }
                               7696                 :                : 
                               7697                 :                : /*
                               7698                 :                :  * apply_typmod_special() -
                               7699                 :                :  *
                               7700                 :                :  *  Do bounds checking according to the specified typmod, for an Inf or NaN.
                               7701                 :                :  *  For convenience of most callers, the value is presented in packed form.
                               7702                 :                :  *
                               7703                 :                :  * Returns true on success, false on failure (if escontext points to an
                               7704                 :                :  * ErrorSaveContext; otherwise errors are thrown).
                               7705                 :                :  */
                               7706                 :                : static bool
                               7707                 :            944 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
                               7708                 :                : {
                               7709                 :                :     int         precision;
                               7710                 :                :     int         scale;
                               7711                 :                : 
 1872                          7712         [ -  + ]:            944 :     Assert(NUMERIC_IS_SPECIAL(num));    /* caller error if not */
                               7713                 :                : 
                               7714                 :                :     /*
                               7715                 :                :      * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
                               7716                 :                :      * but it's a longstanding behavior.  Inf is rejected if we have any
                               7717                 :                :      * typmod restriction, since an infinity shouldn't be claimed to fit in
                               7718                 :                :      * any finite number of digits.
                               7719                 :                :      */
                               7720         [ +  + ]:            944 :     if (NUMERIC_IS_NAN(num))
 1002                          7721                 :            395 :         return true;
                               7722                 :                : 
                               7723                 :                :     /* Do nothing if we have a default typmod (-1) */
 1503 dean.a.rasheed@gmail     7724         [ +  + ]:            549 :     if (!is_valid_numeric_typmod(typmod))
 1002 tgl@sss.pgh.pa.us        7725                 :            540 :         return true;
                               7726                 :                : 
 1503 dean.a.rasheed@gmail     7727                 :              9 :     precision = numeric_typmod_precision(typmod);
                               7728                 :              9 :     scale = numeric_typmod_scale(typmod);
                               7729                 :                : 
 1002 tgl@sss.pgh.pa.us        7730         [ +  - ]:              9 :     ereturn(escontext, false,
                               7731                 :                :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               7732                 :                :              errmsg("numeric field overflow"),
                               7733                 :                :              errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
                               7734                 :                :                        precision, scale)));
                               7735                 :                : }
                               7736                 :                : 
                               7737                 :                : 
                               7738                 :                : /*
                               7739                 :                :  * Convert numeric to int8, rounding if needed.
                               7740                 :                :  *
                               7741                 :                :  * If overflow, return false (no error is raised).  Return true if okay.
                               7742                 :                :  */
                               7743                 :                : static bool
 2918 andres@anarazel.de       7744                 :           5159 : numericvar_to_int64(const NumericVar *var, int64 *result)
                               7745                 :                : {
                               7746                 :                :     NumericDigit *digits;
                               7747                 :                :     int         ndigits;
                               7748                 :                :     int         weight;
                               7749                 :                :     int         i;
                               7750                 :                :     int64       val;
                               7751                 :                :     bool        neg;
                               7752                 :                :     NumericVar  rounded;
                               7753                 :                : 
                               7754                 :                :     /* Round to nearest integer */
 4672 heikki.linnakangas@i     7755                 :           5159 :     init_var(&rounded);
                               7756                 :           5159 :     set_var_from_var(var, &rounded);
                               7757                 :           5159 :     round_var(&rounded, 0);
                               7758                 :                : 
                               7759                 :                :     /* Check for zero input */
                               7760                 :           5159 :     strip_var(&rounded);
                               7761                 :           5159 :     ndigits = rounded.ndigits;
 8205 tgl@sss.pgh.pa.us        7762         [ +  + ]:           5159 :     if (ndigits == 0)
                               7763                 :                :     {
                               7764                 :            237 :         *result = 0;
 4672 heikki.linnakangas@i     7765                 :            237 :         free_var(&rounded);
 8205 tgl@sss.pgh.pa.us        7766                 :            237 :         return true;
                               7767                 :                :     }
                               7768                 :                : 
                               7769                 :                :     /*
                               7770                 :                :      * For input like 10000000000, we must treat stripped digits as real. So
                               7771                 :                :      * the loop assumes there are weight+1 digits before the decimal point.
                               7772                 :                :      */
 4672 heikki.linnakangas@i     7773                 :           4922 :     weight = rounded.weight;
 8069 bruce@momjian.us         7774   [ +  -  -  + ]:           4922 :     Assert(weight >= 0 && ndigits <= weight + 1);
                               7775                 :                : 
                               7776                 :                :     /*
                               7777                 :                :      * Construct the result. To avoid issues with converting a value
                               7778                 :                :      * corresponding to INT64_MIN (which can't be represented as a positive 64
                               7779                 :                :      * bit two's complement integer), accumulate value as a negative number.
                               7780                 :                :      */
 4672 heikki.linnakangas@i     7781                 :           4922 :     digits = rounded.digits;
                               7782                 :           4922 :     neg = (rounded.sign == NUMERIC_NEG);
 2825 andres@anarazel.de       7783                 :           4922 :     val = -digits[0];
 8101 tgl@sss.pgh.pa.us        7784         [ +  + ]:           6988 :     for (i = 1; i <= weight; i++)
                               7785                 :                :     {
 2825 andres@anarazel.de       7786         [ +  + ]:           2090 :         if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
                               7787                 :                :         {
                               7788                 :             15 :             free_var(&rounded);
                               7789                 :             15 :             return false;
                               7790                 :                :         }
                               7791                 :                : 
                               7792         [ +  + ]:           2075 :         if (i < ndigits)
                               7793                 :                :         {
                               7794         [ +  + ]:           1937 :             if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
                               7795                 :                :             {
 4672 heikki.linnakangas@i     7796                 :              9 :                 free_var(&rounded);
 8205 tgl@sss.pgh.pa.us        7797                 :              9 :                 return false;
                               7798                 :                :             }
                               7799                 :                :         }
                               7800                 :                :     }
                               7801                 :                : 
 4672 heikki.linnakangas@i     7802                 :           4898 :     free_var(&rounded);
                               7803                 :                : 
 2825 andres@anarazel.de       7804         [ +  + ]:           4898 :     if (!neg)
                               7805                 :                :     {
                               7806         [ +  + ]:           4502 :         if (unlikely(val == PG_INT64_MIN))
                               7807                 :             12 :             return false;
                               7808                 :           4490 :         val = -val;
                               7809                 :                :     }
                               7810                 :           4886 :     *result = val;
                               7811                 :                : 
 8205 tgl@sss.pgh.pa.us        7812                 :           4886 :     return true;
                               7813                 :                : }
                               7814                 :                : 
                               7815                 :                : /*
                               7816                 :                :  * Convert int8 value to numeric.
                               7817                 :                :  */
                               7818                 :                : static void
 3823 andres@anarazel.de       7819                 :         949707 : int64_to_numericvar(int64 val, NumericVar *var)
                               7820                 :                : {
                               7821                 :                :     uint64      uval,
                               7822                 :                :                 newuval;
                               7823                 :                :     NumericDigit *ptr;
                               7824                 :                :     int         ndigits;
                               7825                 :                : 
                               7826                 :                :     /* int64 can require at most 19 decimal digits; add one for safety */
 8069 bruce@momjian.us         7827                 :         949707 :     alloc_var(var, 20 / DEC_DIGITS);
 8205 tgl@sss.pgh.pa.us        7828         [ +  + ]:         949707 :     if (val < 0)
                               7829                 :                :     {
                               7830                 :            904 :         var->sign = NUMERIC_NEG;
  387 nathan@postgresql.or     7831                 :            904 :         uval = pg_abs_s64(val);
                               7832                 :                :     }
                               7833                 :                :     else
                               7834                 :                :     {
 8205 tgl@sss.pgh.pa.us        7835                 :         948803 :         var->sign = NUMERIC_POS;
                               7836                 :         948803 :         uval = val;
                               7837                 :                :     }
                               7838                 :         949707 :     var->dscale = 0;
                               7839         [ +  + ]:         949707 :     if (val == 0)
                               7840                 :                :     {
                               7841                 :          15333 :         var->ndigits = 0;
                               7842                 :          15333 :         var->weight = 0;
                               7843                 :          15333 :         return;
                               7844                 :                :     }
                               7845                 :         934374 :     ptr = var->digits + var->ndigits;
                               7846                 :         934374 :     ndigits = 0;
                               7847                 :                :     do
                               7848                 :                :     {
                               7849                 :        1096090 :         ptr--;
                               7850                 :        1096090 :         ndigits++;
                               7851                 :        1096090 :         newuval = uval / NBASE;
                               7852                 :        1096090 :         *ptr = uval - newuval * NBASE;
                               7853                 :        1096090 :         uval = newuval;
                               7854         [ +  + ]:        1096090 :     } while (uval);
                               7855                 :         934374 :     var->digits = ptr;
                               7856                 :         934374 :     var->ndigits = ndigits;
                               7857                 :         934374 :     var->weight = ndigits - 1;
                               7858                 :                : }
                               7859                 :                : 
                               7860                 :                : /*
                               7861                 :                :  * Convert numeric to uint64, rounding if needed.
                               7862                 :                :  *
                               7863                 :                :  * If overflow, return false (no error is raised).  Return true if okay.
                               7864                 :                :  */
                               7865                 :                : static bool
 1894 fujii@postgresql.org     7866                 :             57 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
                               7867                 :                : {
                               7868                 :                :     NumericDigit *digits;
                               7869                 :                :     int         ndigits;
                               7870                 :                :     int         weight;
                               7871                 :                :     int         i;
                               7872                 :                :     uint64      val;
                               7873                 :                :     NumericVar  rounded;
                               7874                 :                : 
                               7875                 :                :     /* Round to nearest integer */
                               7876                 :             57 :     init_var(&rounded);
                               7877                 :             57 :     set_var_from_var(var, &rounded);
                               7878                 :             57 :     round_var(&rounded, 0);
                               7879                 :                : 
                               7880                 :                :     /* Check for zero input */
                               7881                 :             57 :     strip_var(&rounded);
                               7882                 :             57 :     ndigits = rounded.ndigits;
                               7883         [ +  + ]:             57 :     if (ndigits == 0)
                               7884                 :                :     {
                               7885                 :              9 :         *result = 0;
                               7886                 :              9 :         free_var(&rounded);
                               7887                 :              9 :         return true;
                               7888                 :                :     }
                               7889                 :                : 
                               7890                 :                :     /* Check for negative input */
                               7891         [ +  + ]:             48 :     if (rounded.sign == NUMERIC_NEG)
                               7892                 :                :     {
                               7893                 :              6 :         free_var(&rounded);
                               7894                 :              6 :         return false;
                               7895                 :                :     }
                               7896                 :                : 
                               7897                 :                :     /*
                               7898                 :                :      * For input like 10000000000, we must treat stripped digits as real. So
                               7899                 :                :      * the loop assumes there are weight+1 digits before the decimal point.
                               7900                 :                :      */
                               7901                 :             42 :     weight = rounded.weight;
                               7902   [ +  -  -  + ]:             42 :     Assert(weight >= 0 && ndigits <= weight + 1);
                               7903                 :                : 
                               7904                 :                :     /* Construct the result */
                               7905                 :             42 :     digits = rounded.digits;
                               7906                 :             42 :     val = digits[0];
                               7907         [ +  + ]:            123 :     for (i = 1; i <= weight; i++)
                               7908                 :                :     {
                               7909         [ -  + ]:             87 :         if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
                               7910                 :                :         {
 1894 fujii@postgresql.org     7911                 :UBC           0 :             free_var(&rounded);
                               7912                 :              0 :             return false;
                               7913                 :                :         }
                               7914                 :                : 
 1894 fujii@postgresql.org     7915         [ +  - ]:CBC          87 :         if (i < ndigits)
                               7916                 :                :         {
                               7917         [ +  + ]:             87 :             if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
                               7918                 :                :             {
                               7919                 :              6 :                 free_var(&rounded);
                               7920                 :              6 :                 return false;
                               7921                 :                :             }
                               7922                 :                :         }
                               7923                 :                :     }
                               7924                 :                : 
                               7925                 :             36 :     free_var(&rounded);
                               7926                 :                : 
                               7927                 :             36 :     *result = val;
                               7928                 :                : 
                               7929                 :             36 :     return true;
                               7930                 :                : }
                               7931                 :                : 
                               7932                 :                : /*
                               7933                 :                :  * Convert 128 bit integer to numeric.
                               7934                 :                :  */
                               7935                 :                : static void
   30 dean.a.rasheed@gmail     7936                 :GNC        4397 : int128_to_numericvar(INT128 val, NumericVar *var)
                               7937                 :                : {
                               7938                 :                :     int         sign;
                               7939                 :                :     NumericDigit *ptr;
                               7940                 :                :     int         ndigits;
                               7941                 :                :     int32       dig;
                               7942                 :                : 
                               7943                 :                :     /* int128 can require at most 39 decimal digits; add one for safety */
 3823 andres@anarazel.de       7944                 :CBC        4397 :     alloc_var(var, 40 / DEC_DIGITS);
   30 dean.a.rasheed@gmail     7945                 :GNC        4397 :     sign = int128_sign(val);
                               7946                 :           4397 :     var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS;
 3823 andres@anarazel.de       7947                 :CBC        4397 :     var->dscale = 0;
   30 dean.a.rasheed@gmail     7948         [ +  + ]:GNC        4397 :     if (sign == 0)
                               7949                 :                :     {
 3823 andres@anarazel.de       7950                 :CBC         105 :         var->ndigits = 0;
                               7951                 :            105 :         var->weight = 0;
                               7952                 :            105 :         return;
                               7953                 :                :     }
                               7954                 :           4292 :     ptr = var->digits + var->ndigits;
                               7955                 :           4292 :     ndigits = 0;
                               7956                 :                :     do
                               7957                 :                :     {
                               7958                 :          22620 :         ptr--;
                               7959                 :          22620 :         ndigits++;
   30 dean.a.rasheed@gmail     7960                 :GNC       22620 :         int128_div_mod_int32(&val, NBASE, &dig);
                               7961                 :          22620 :         *ptr = (NumericDigit) abs(dig);
                               7962         [ +  + ]:          22620 :     } while (!int128_is_zero(val));
 3823 andres@anarazel.de       7963                 :CBC        4292 :     var->digits = ptr;
                               7964                 :           4292 :     var->ndigits = ndigits;
                               7965                 :           4292 :     var->weight = ndigits - 1;
                               7966                 :                : }
                               7967                 :                : 
                               7968                 :                : /*
                               7969                 :                :  * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
                               7970                 :                :  */
                               7971                 :                : static double
 2918                          7972                 :            233 : numericvar_to_double_no_overflow(const NumericVar *var)
                               7973                 :                : {
                               7974                 :                :     char       *tmp;
                               7975                 :                :     double      val;
                               7976                 :                :     char       *endptr;
                               7977                 :                : 
 4672 heikki.linnakangas@i     7978                 :            233 :     tmp = get_str_from_var(var);
                               7979                 :                : 
                               7980                 :                :     /* unlike float8in, we ignore ERANGE from strtod */
 8375 tgl@sss.pgh.pa.us        7981                 :            233 :     val = strtod(tmp, &endptr);
                               7982         [ -  + ]:            233 :     if (*endptr != '\0')
                               7983                 :                :     {
                               7984                 :                :         /* shouldn't happen ... */
 8077 tgl@sss.pgh.pa.us        7985         [ #  # ]:UBC           0 :         ereport(ERROR,
                               7986                 :                :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               7987                 :                :                  errmsg("invalid input syntax for type %s: \"%s\"",
                               7988                 :                :                         "double precision", tmp)));
                               7989                 :                :     }
                               7990                 :                : 
 8375 tgl@sss.pgh.pa.us        7991                 :CBC         233 :     pfree(tmp);
                               7992                 :                : 
                               7993                 :            233 :     return val;
                               7994                 :                : }
                               7995                 :                : 
                               7996                 :                : 
                               7997                 :                : /*
                               7998                 :                :  * cmp_var() -
                               7999                 :                :  *
                               8000                 :                :  *  Compare two values on variable level.  We assume zeroes have been
                               8001                 :                :  *  truncated to no digits.
                               8002                 :                :  */
                               8003                 :                : static int
 2918 andres@anarazel.de       8004                 :          85114 : cmp_var(const NumericVar *var1, const NumericVar *var2)
                               8005                 :                : {
 7151 bruce@momjian.us         8006                 :         170228 :     return cmp_var_common(var1->digits, var1->ndigits,
                               8007                 :          85114 :                           var1->weight, var1->sign,
                               8008                 :          85114 :                           var2->digits, var2->ndigits,
                               8009                 :          85114 :                           var2->weight, var2->sign);
                               8010                 :                : }
                               8011                 :                : 
                               8012                 :                : /*
                               8013                 :                :  * cmp_var_common() -
                               8014                 :                :  *
                               8015                 :                :  *  Main routine of cmp_var(). This function can be used by both
                               8016                 :                :  *  NumericVar and Numeric.
                               8017                 :                :  */
                               8018                 :                : static int
                               8019                 :        9978399 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
                               8020                 :                :                int var1weight, int var1sign,
                               8021                 :                :                const NumericDigit *var2digits, int var2ndigits,
                               8022                 :                :                int var2weight, int var2sign)
                               8023                 :                : {
                               8024         [ +  + ]:        9978399 :     if (var1ndigits == 0)
                               8025                 :                :     {
                               8026         [ +  + ]:         271497 :         if (var2ndigits == 0)
 9747 JanWieck@Yahoo.com       8027                 :         222515 :             return 0;
 7151 bruce@momjian.us         8028         [ +  + ]:          48982 :         if (var2sign == NUMERIC_NEG)
 9747 JanWieck@Yahoo.com       8029                 :           2163 :             return 1;
                               8030                 :          46819 :         return -1;
                               8031                 :                :     }
 7151 bruce@momjian.us         8032         [ +  + ]:        9706902 :     if (var2ndigits == 0)
                               8033                 :                :     {
                               8034         [ +  + ]:          36650 :         if (var1sign == NUMERIC_POS)
 9747 JanWieck@Yahoo.com       8035                 :          33014 :             return 1;
                               8036                 :           3636 :         return -1;
                               8037                 :                :     }
                               8038                 :                : 
 7151 bruce@momjian.us         8039         [ +  + ]:        9670252 :     if (var1sign == NUMERIC_POS)
                               8040                 :                :     {
                               8041         [ +  + ]:        9627639 :         if (var2sign == NUMERIC_NEG)
 9747 JanWieck@Yahoo.com       8042                 :          11719 :             return 1;
 7151 bruce@momjian.us         8043                 :        9615920 :         return cmp_abs_common(var1digits, var1ndigits, var1weight,
                               8044                 :                :                               var2digits, var2ndigits, var2weight);
                               8045                 :                :     }
                               8046                 :                : 
                               8047         [ +  + ]:          42613 :     if (var2sign == NUMERIC_POS)
 9747 JanWieck@Yahoo.com       8048                 :          11832 :         return -1;
                               8049                 :                : 
 7151 bruce@momjian.us         8050                 :          30781 :     return cmp_abs_common(var2digits, var2ndigits, var2weight,
                               8051                 :                :                           var1digits, var1ndigits, var1weight);
                               8052                 :                : }
                               8053                 :                : 
                               8054                 :                : 
                               8055                 :                : /*
                               8056                 :                :  * add_var() -
                               8057                 :                :  *
                               8058                 :                :  *  Full version of add functionality on variable level (handling signs).
                               8059                 :                :  *  result might point to one of the operands too without danger.
                               8060                 :                :  */
                               8061                 :                : static void
 2918 andres@anarazel.de       8062                 :         309056 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               8063                 :                : {
                               8064                 :                :     /*
                               8065                 :                :      * Decide on the signs of the two variables what to do
                               8066                 :                :      */
 9747 JanWieck@Yahoo.com       8067         [ +  + ]:         309056 :     if (var1->sign == NUMERIC_POS)
                               8068                 :                :     {
                               8069         [ +  + ]:         308273 :         if (var2->sign == NUMERIC_POS)
                               8070                 :                :         {
                               8071                 :                :             /*
                               8072                 :                :              * Both are positive result = +(ABS(var1) + ABS(var2))
                               8073                 :                :              */
                               8074                 :         208085 :             add_abs(var1, var2, result);
                               8075                 :         208085 :             result->sign = NUMERIC_POS;
                               8076                 :                :         }
                               8077                 :                :         else
                               8078                 :                :         {
                               8079                 :                :             /*
                               8080                 :                :              * var1 is positive, var2 is negative Must compare absolute values
                               8081                 :                :              */
                               8082   [ +  +  +  - ]:         100188 :             switch (cmp_abs(var1, var2))
                               8083                 :                :             {
 9182 tgl@sss.pgh.pa.us        8084                 :            104 :                 case 0:
                               8085                 :                :                     /* ----------
                               8086                 :                :                      * ABS(var1) == ABS(var2)
                               8087                 :                :                      * result = ZERO
                               8088                 :                :                      * ----------
                               8089                 :                :                      */
 9363                          8090                 :            104 :                     zero_var(result);
 8601 bruce@momjian.us         8091                 :            104 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9601                          8092                 :            104 :                     break;
                               8093                 :                : 
 9182 tgl@sss.pgh.pa.us        8094                 :          93197 :                 case 1:
                               8095                 :                :                     /* ----------
                               8096                 :                :                      * ABS(var1) > ABS(var2)
                               8097                 :                :                      * result = +(ABS(var1) - ABS(var2))
                               8098                 :                :                      * ----------
                               8099                 :                :                      */
 9601 bruce@momjian.us         8100                 :          93197 :                     sub_abs(var1, var2, result);
                               8101                 :          93197 :                     result->sign = NUMERIC_POS;
                               8102                 :          93197 :                     break;
                               8103                 :                : 
 9182 tgl@sss.pgh.pa.us        8104                 :           6887 :                 case -1:
                               8105                 :                :                     /* ----------
                               8106                 :                :                      * ABS(var1) < ABS(var2)
                               8107                 :                :                      * result = -(ABS(var2) - ABS(var1))
                               8108                 :                :                      * ----------
                               8109                 :                :                      */
 9601 bruce@momjian.us         8110                 :           6887 :                     sub_abs(var2, var1, result);
                               8111                 :           6887 :                     result->sign = NUMERIC_NEG;
                               8112                 :           6887 :                     break;
                               8113                 :                :             }
                               8114                 :                :         }
                               8115                 :                :     }
                               8116                 :                :     else
                               8117                 :                :     {
 9747 JanWieck@Yahoo.com       8118         [ +  + ]:            783 :         if (var2->sign == NUMERIC_POS)
                               8119                 :                :         {
                               8120                 :                :             /* ----------
                               8121                 :                :              * var1 is negative, var2 is positive
                               8122                 :                :              * Must compare absolute values
                               8123                 :                :              * ----------
                               8124                 :                :              */
                               8125   [ +  +  +  - ]:            234 :             switch (cmp_abs(var1, var2))
                               8126                 :                :             {
 9182 tgl@sss.pgh.pa.us        8127                 :             15 :                 case 0:
                               8128                 :                :                     /* ----------
                               8129                 :                :                      * ABS(var1) == ABS(var2)
                               8130                 :                :                      * result = ZERO
                               8131                 :                :                      * ----------
                               8132                 :                :                      */
 9363                          8133                 :             15 :                     zero_var(result);
 8601 bruce@momjian.us         8134                 :             15 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9601                          8135                 :             15 :                     break;
                               8136                 :                : 
 9182 tgl@sss.pgh.pa.us        8137                 :            147 :                 case 1:
                               8138                 :                :                     /* ----------
                               8139                 :                :                      * ABS(var1) > ABS(var2)
                               8140                 :                :                      * result = -(ABS(var1) - ABS(var2))
                               8141                 :                :                      * ----------
                               8142                 :                :                      */
 9601 bruce@momjian.us         8143                 :            147 :                     sub_abs(var1, var2, result);
                               8144                 :            147 :                     result->sign = NUMERIC_NEG;
                               8145                 :            147 :                     break;
                               8146                 :                : 
 9182 tgl@sss.pgh.pa.us        8147                 :             72 :                 case -1:
                               8148                 :                :                     /* ----------
                               8149                 :                :                      * ABS(var1) < ABS(var2)
                               8150                 :                :                      * result = +(ABS(var2) - ABS(var1))
                               8151                 :                :                      * ----------
                               8152                 :                :                      */
 9601 bruce@momjian.us         8153                 :             72 :                     sub_abs(var2, var1, result);
                               8154                 :             72 :                     result->sign = NUMERIC_POS;
                               8155                 :             72 :                     break;
                               8156                 :                :             }
                               8157                 :                :         }
                               8158                 :                :         else
                               8159                 :                :         {
                               8160                 :                :             /* ----------
                               8161                 :                :              * Both are negative
                               8162                 :                :              * result = -(ABS(var1) + ABS(var2))
                               8163                 :                :              * ----------
                               8164                 :                :              */
 9747 JanWieck@Yahoo.com       8165                 :            549 :             add_abs(var1, var2, result);
                               8166                 :            549 :             result->sign = NUMERIC_NEG;
                               8167                 :                :         }
                               8168                 :                :     }
                               8169                 :         309056 : }
                               8170                 :                : 
                               8171                 :                : 
                               8172                 :                : /*
                               8173                 :                :  * sub_var() -
                               8174                 :                :  *
                               8175                 :                :  *  Full version of sub functionality on variable level (handling signs).
                               8176                 :                :  *  result might point to one of the operands too without danger.
                               8177                 :                :  */
                               8178                 :                : static void
 2918 andres@anarazel.de       8179                 :         266306 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               8180                 :                : {
                               8181                 :                :     /*
                               8182                 :                :      * Decide on the signs of the two variables what to do
                               8183                 :                :      */
 9747 JanWieck@Yahoo.com       8184         [ +  + ]:         266306 :     if (var1->sign == NUMERIC_POS)
                               8185                 :                :     {
                               8186         [ +  + ]:         265851 :         if (var2->sign == NUMERIC_NEG)
                               8187                 :                :         {
                               8188                 :                :             /* ----------
                               8189                 :                :              * var1 is positive, var2 is negative
                               8190                 :                :              * result = +(ABS(var1) + ABS(var2))
                               8191                 :                :              * ----------
                               8192                 :                :              */
                               8193                 :          14207 :             add_abs(var1, var2, result);
                               8194                 :          14207 :             result->sign = NUMERIC_POS;
                               8195                 :                :         }
                               8196                 :                :         else
                               8197                 :                :         {
                               8198                 :                :             /* ----------
                               8199                 :                :              * Both are positive
                               8200                 :                :              * Must compare absolute values
                               8201                 :                :              * ----------
                               8202                 :                :              */
                               8203   [ +  +  +  - ]:         251644 :             switch (cmp_abs(var1, var2))
                               8204                 :                :             {
 9182 tgl@sss.pgh.pa.us        8205                 :          24481 :                 case 0:
                               8206                 :                :                     /* ----------
                               8207                 :                :                      * ABS(var1) == ABS(var2)
                               8208                 :                :                      * result = ZERO
                               8209                 :                :                      * ----------
                               8210                 :                :                      */
 9363                          8211                 :          24481 :                     zero_var(result);
 8601 bruce@momjian.us         8212                 :          24481 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9601                          8213                 :          24481 :                     break;
                               8214                 :                : 
 9182 tgl@sss.pgh.pa.us        8215                 :         223380 :                 case 1:
                               8216                 :                :                     /* ----------
                               8217                 :                :                      * ABS(var1) > ABS(var2)
                               8218                 :                :                      * result = +(ABS(var1) - ABS(var2))
                               8219                 :                :                      * ----------
                               8220                 :                :                      */
 9601 bruce@momjian.us         8221                 :         223380 :                     sub_abs(var1, var2, result);
                               8222                 :         223380 :                     result->sign = NUMERIC_POS;
                               8223                 :         223380 :                     break;
                               8224                 :                : 
 9182 tgl@sss.pgh.pa.us        8225                 :           3783 :                 case -1:
                               8226                 :                :                     /* ----------
                               8227                 :                :                      * ABS(var1) < ABS(var2)
                               8228                 :                :                      * result = -(ABS(var2) - ABS(var1))
                               8229                 :                :                      * ----------
                               8230                 :                :                      */
 9601 bruce@momjian.us         8231                 :           3783 :                     sub_abs(var2, var1, result);
                               8232                 :           3783 :                     result->sign = NUMERIC_NEG;
                               8233                 :           3783 :                     break;
                               8234                 :                :             }
                               8235                 :                :         }
                               8236                 :                :     }
                               8237                 :                :     else
                               8238                 :                :     {
 9747 JanWieck@Yahoo.com       8239         [ +  + ]:            455 :         if (var2->sign == NUMERIC_NEG)
                               8240                 :                :         {
                               8241                 :                :             /* ----------
                               8242                 :                :              * Both are negative
                               8243                 :                :              * Must compare absolute values
                               8244                 :                :              * ----------
                               8245                 :                :              */
                               8246   [ +  +  +  - ]:            227 :             switch (cmp_abs(var1, var2))
                               8247                 :                :             {
 9182 tgl@sss.pgh.pa.us        8248                 :             83 :                 case 0:
                               8249                 :                :                     /* ----------
                               8250                 :                :                      * ABS(var1) == ABS(var2)
                               8251                 :                :                      * result = ZERO
                               8252                 :                :                      * ----------
                               8253                 :                :                      */
 9363                          8254                 :             83 :                     zero_var(result);
 8601 bruce@momjian.us         8255                 :             83 :                     result->dscale = Max(var1->dscale, var2->dscale);
 9601                          8256                 :             83 :                     break;
                               8257                 :                : 
 9182 tgl@sss.pgh.pa.us        8258                 :            120 :                 case 1:
                               8259                 :                :                     /* ----------
                               8260                 :                :                      * ABS(var1) > ABS(var2)
                               8261                 :                :                      * result = -(ABS(var1) - ABS(var2))
                               8262                 :                :                      * ----------
                               8263                 :                :                      */
 9601 bruce@momjian.us         8264                 :            120 :                     sub_abs(var1, var2, result);
                               8265                 :            120 :                     result->sign = NUMERIC_NEG;
                               8266                 :            120 :                     break;
                               8267                 :                : 
 9182 tgl@sss.pgh.pa.us        8268                 :             24 :                 case -1:
                               8269                 :                :                     /* ----------
                               8270                 :                :                      * ABS(var1) < ABS(var2)
                               8271                 :                :                      * result = +(ABS(var2) - ABS(var1))
                               8272                 :                :                      * ----------
                               8273                 :                :                      */
 9601 bruce@momjian.us         8274                 :             24 :                     sub_abs(var2, var1, result);
                               8275                 :             24 :                     result->sign = NUMERIC_POS;
                               8276                 :             24 :                     break;
                               8277                 :                :             }
                               8278                 :                :         }
                               8279                 :                :         else
                               8280                 :                :         {
                               8281                 :                :             /* ----------
                               8282                 :                :              * var1 is negative, var2 is positive
                               8283                 :                :              * result = -(ABS(var1) + ABS(var2))
                               8284                 :                :              * ----------
                               8285                 :                :              */
 9747 JanWieck@Yahoo.com       8286                 :            228 :             add_abs(var1, var2, result);
                               8287                 :            228 :             result->sign = NUMERIC_NEG;
                               8288                 :                :         }
                               8289                 :                :     }
                               8290                 :         266306 : }
                               8291                 :                : 
                               8292                 :                : 
                               8293                 :                : /*
                               8294                 :                :  * mul_var() -
                               8295                 :                :  *
                               8296                 :                :  *  Multiplication on variable level. Product of var1 * var2 is stored
                               8297                 :                :  *  in result.  Result is rounded to no more than rscale fractional digits.
                               8298                 :                :  */
                               8299                 :                : static void
 2918 andres@anarazel.de       8300                 :         594861 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
                               8301                 :                :         int rscale)
                               8302                 :                : {
                               8303                 :                :     int         res_ndigits;
                               8304                 :                :     int         res_ndigitpairs;
                               8305                 :                :     int         res_sign;
                               8306                 :                :     int         res_weight;
                               8307                 :                :     int         pair_offset;
                               8308                 :                :     int         maxdigits;
                               8309                 :                :     int         maxdigitpairs;
                               8310                 :                :     uint64     *dig,
                               8311                 :                :                *dig_i1_off;
                               8312                 :                :     uint64      maxdig;
                               8313                 :                :     uint64      carry;
                               8314                 :                :     uint64      newdig;
                               8315                 :                :     int         var1ndigits;
                               8316                 :                :     int         var2ndigits;
                               8317                 :                :     int         var1ndigitpairs;
                               8318                 :                :     int         var2ndigitpairs;
                               8319                 :                :     NumericDigit *var1digits;
                               8320                 :                :     NumericDigit *var2digits;
                               8321                 :                :     uint32      var1digitpair;
                               8322                 :                :     uint32     *var2digitpairs;
                               8323                 :                :     NumericDigit *res_digits;
                               8324                 :                :     int         i,
                               8325                 :                :                 i1,
                               8326                 :                :                 i2,
                               8327                 :                :                 i2limit;
                               8328                 :                : 
                               8329                 :                :     /*
                               8330                 :                :      * Arrange for var1 to be the shorter of the two numbers.  This improves
                               8331                 :                :      * performance because the inner multiplication loop is much simpler than
                               8332                 :                :      * the outer loop, so it's better to have a smaller number of iterations
                               8333                 :                :      * of the outer loop.  This also reduces the number of times that the
                               8334                 :                :      * accumulator array needs to be normalized.
                               8335                 :                :      */
 3584 tgl@sss.pgh.pa.us        8336         [ +  + ]:         594861 :     if (var1->ndigits > var2->ndigits)
                               8337                 :                :     {
 2918 andres@anarazel.de       8338                 :           7571 :         const NumericVar *tmp = var1;
                               8339                 :                : 
 3584 tgl@sss.pgh.pa.us        8340                 :           7571 :         var1 = var2;
                               8341                 :           7571 :         var2 = tmp;
                               8342                 :                :     }
                               8343                 :                : 
                               8344                 :                :     /* copy these values into local vars for speed in inner loop */
                               8345                 :         594861 :     var1ndigits = var1->ndigits;
                               8346                 :         594861 :     var2ndigits = var2->ndigits;
                               8347                 :         594861 :     var1digits = var1->digits;
                               8348                 :         594861 :     var2digits = var2->digits;
                               8349                 :                : 
  424 dean.a.rasheed@gmail     8350         [ +  + ]:         594861 :     if (var1ndigits == 0)
                               8351                 :                :     {
                               8352                 :                :         /* one or both inputs is zero; so is result */
 8205 tgl@sss.pgh.pa.us        8353                 :           1447 :         zero_var(result);
                               8354                 :           1447 :         result->dscale = rscale;
                               8355                 :           1447 :         return;
                               8356                 :                :     }
                               8357                 :                : 
                               8358                 :                :     /*
                               8359                 :                :      * If var1 has 1-6 digits and the exact result was requested, delegate to
                               8360                 :                :      * mul_var_short() which uses a faster direct multiplication algorithm.
                               8361                 :                :      */
  387 dean.a.rasheed@gmail     8362   [ +  +  +  + ]:         593414 :     if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
                               8363                 :                :     {
  424                          8364                 :         579176 :         mul_var_short(var1, var2, result);
                               8365                 :         579176 :         return;
                               8366                 :                :     }
                               8367                 :                : 
                               8368                 :                :     /* Determine result sign */
 9747 JanWieck@Yahoo.com       8369         [ +  + ]:          14238 :     if (var1->sign == var2->sign)
                               8370                 :          13497 :         res_sign = NUMERIC_POS;
                               8371                 :                :     else
                               8372                 :            741 :         res_sign = NUMERIC_NEG;
                               8373                 :                : 
                               8374                 :                :     /*
                               8375                 :                :      * Determine the number of result digits to compute and the (maximum
                               8376                 :                :      * possible) result weight.  If the exact result would have more than
                               8377                 :                :      * rscale fractional digits, truncate the computation with
                               8378                 :                :      * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
                               8379                 :                :      * only contribute to the right of that.  (This will give the exact
                               8380                 :                :      * rounded-to-rscale answer unless carries out of the ignored positions
                               8381                 :                :      * would have propagated through more than MUL_GUARD_DIGITS digits.)
                               8382                 :                :      *
                               8383                 :                :      * Note: an exact computation could not produce more than var1ndigits +
                               8384                 :                :      * var2ndigits digits, but we allocate at least one extra output digit in
                               8385                 :                :      * case rscale-driven rounding produces a carry out of the highest exact
                               8386                 :                :      * digit.
                               8387                 :                :      *
                               8388                 :                :      * The computation itself is done using base-NBASE^2 arithmetic, so we
                               8389                 :                :      * actually process the input digits in pairs, producing a base-NBASE^2
                               8390                 :                :      * intermediate result.  This significantly improves performance, since
                               8391                 :                :      * schoolbook multiplication is O(N^2) in the number of input digits, and
                               8392                 :                :      * working in base NBASE^2 effectively halves "N".
                               8393                 :                :      *
                               8394                 :                :      * Note: in a truncated computation, we must compute at least one extra
                               8395                 :                :      * output digit to ensure that all the guard digits are fully computed.
                               8396                 :                :      */
                               8397                 :                :     /* digit pairs in each input */
  387 dean.a.rasheed@gmail     8398                 :          14238 :     var1ndigitpairs = (var1ndigits + 1) / 2;
                               8399                 :          14238 :     var2ndigitpairs = (var2ndigits + 1) / 2;
                               8400                 :                : 
                               8401                 :                :     /* digits in exact result */
                               8402                 :          14238 :     res_ndigits = var1ndigits + var2ndigits;
                               8403                 :                : 
                               8404                 :                :     /* digit pairs in exact result with at least one extra output digit */
                               8405                 :          14238 :     res_ndigitpairs = res_ndigits / 2 + 1;
                               8406                 :                : 
                               8407                 :                :     /* pair offset to align result to end of dig[] */
                               8408                 :          14238 :     pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
                               8409                 :                : 
                               8410                 :                :     /* maximum possible result weight (odd-length inputs shifted up below) */
                               8411                 :          14238 :     res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
                               8412                 :          14238 :         res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
                               8413                 :                : 
                               8414                 :                :     /* rscale-based truncation with at least one extra output digit */
 3584 tgl@sss.pgh.pa.us        8415                 :          14238 :     maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
                               8416                 :                :         MUL_GUARD_DIGITS;
  387 dean.a.rasheed@gmail     8417                 :          14238 :     maxdigitpairs = maxdigits / 2 + 1;
                               8418                 :                : 
                               8419                 :          14238 :     res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
                               8420                 :          14238 :     res_ndigits = 2 * res_ndigitpairs;
                               8421                 :                : 
                               8422                 :                :     /*
                               8423                 :                :      * In the computation below, digit pair i1 of var1 and digit pair i2 of
                               8424                 :                :      * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
                               8425                 :                :      * input digit pairs with index >= res_ndigitpairs - pair_offset don't
                               8426                 :                :      * contribute to the result, and can be ignored.
                               8427                 :                :      */
                               8428         [ +  + ]:          14238 :     if (res_ndigitpairs <= pair_offset)
                               8429                 :                :     {
                               8430                 :                :         /* All input digits will be ignored; so result is zero */
 3584 tgl@sss.pgh.pa.us        8431                 :              6 :         zero_var(result);
                               8432                 :              6 :         result->dscale = rscale;
                               8433                 :              6 :         return;
                               8434                 :                :     }
  387 dean.a.rasheed@gmail     8435                 :          14232 :     var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
                               8436                 :          14232 :     var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
                               8437                 :                : 
                               8438                 :                :     /*
                               8439                 :                :      * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
                               8440                 :                :      * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
                               8441                 :                :      * headroom to avoid normalizing carries immediately.
                               8442                 :                :      *
                               8443                 :                :      * maxdig tracks the maximum possible value of any dig[] entry; when this
                               8444                 :                :      * threatens to exceed PG_UINT64_MAX, we take the time to propagate
                               8445                 :                :      * carries.  Furthermore, we need to ensure that overflow doesn't occur
                               8446                 :                :      * during the carry propagation passes either.  The carry values could be
                               8447                 :                :      * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
                               8448                 :                :      * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
                               8449                 :                :      *
                               8450                 :                :      * To avoid overflow in maxdig itself, it actually represents the maximum
                               8451                 :                :      * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
                               8452                 :                :      * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
                               8453                 :                :      *
                               8454                 :                :      * The conversion of var1 to base NBASE^2 is done on the fly, as each new
                               8455                 :                :      * digit is required.  The digits of var2 are converted upfront, and
                               8456                 :                :      * stored at the end of dig[].  To avoid loss of precision, the input
                               8457                 :                :      * digits are aligned with the start of digit pair array, effectively
                               8458                 :                :      * shifting them up (multiplying by NBASE) if the inputs have an odd
                               8459                 :                :      * number of NBASE digits.
                               8460                 :                :      */
                               8461                 :          14232 :     dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
                               8462                 :                :                             var2ndigitpairs * sizeof(uint32));
                               8463                 :                : 
                               8464                 :                :     /* convert var2 to base NBASE^2, shifting up if its length is odd */
                               8465                 :          14232 :     var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
                               8466                 :                : 
                               8467         [ +  + ]:         773595 :     for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
                               8468                 :         759363 :         var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
                               8469                 :                : 
                               8470         [ +  + ]:          14232 :     if (2 * i2 + 1 < var2ndigits)
                               8471                 :          10224 :         var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
                               8472                 :                :     else
                               8473                 :           4008 :         var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
                               8474                 :                : 
                               8475                 :                :     /*
                               8476                 :                :      * Start by multiplying var2 by the least significant contributing digit
                               8477                 :                :      * pair from var1, storing the results at the end of dig[], and filling
                               8478                 :                :      * the leading digits with zeros.
                               8479                 :                :      *
                               8480                 :                :      * The loop here is the same as the inner loop below, except that we set
                               8481                 :                :      * the results in dig[], rather than adding to them.  This is the
                               8482                 :                :      * performance bottleneck for multiplication, so we want to keep it simple
                               8483                 :                :      * enough so that it can be auto-vectorized.  Accordingly, process the
                               8484                 :                :      * digits left-to-right even though schoolbook multiplication would
                               8485                 :                :      * suggest right-to-left.  Since we aren't propagating carries in this
                               8486                 :                :      * loop, the order does not matter.
                               8487                 :                :      */
                               8488                 :          14232 :     i1 = var1ndigitpairs - 1;
                               8489         [ +  + ]:          14232 :     if (2 * i1 + 1 < var1ndigits)
                               8490                 :           6360 :         var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
                               8491                 :                :     else
                               8492                 :           7872 :         var1digitpair = var1digits[2 * i1] * NBASE;
                               8493                 :          14232 :     maxdig = var1digitpair;
                               8494                 :                : 
                               8495                 :          14232 :     i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
                               8496                 :          14232 :     dig_i1_off = &dig[i1 + pair_offset];
                               8497                 :                : 
                               8498                 :          14232 :     memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
                               8499         [ +  + ]:         688311 :     for (i2 = 0; i2 < i2limit; i2++)
                               8500                 :         674079 :         dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
                               8501                 :                : 
                               8502                 :                :     /*
                               8503                 :                :      * Next, multiply var2 by the remaining digit pairs from var1, adding the
                               8504                 :                :      * results to dig[] at the appropriate offsets, and normalizing whenever
                               8505                 :                :      * there is a risk of any dig[] entry overflowing.
                               8506                 :                :      */
                               8507         [ +  + ]:         750855 :     for (i1 = i1 - 1; i1 >= 0; i1--)
                               8508                 :                :     {
                               8509                 :         736623 :         var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
                               8510         [ +  + ]:         736623 :         if (var1digitpair == 0)
 8205 tgl@sss.pgh.pa.us        8511                 :         589758 :             continue;
                               8512                 :                : 
                               8513                 :                :         /* Time to normalize? */
  387 dean.a.rasheed@gmail     8514                 :         146865 :         maxdig += var1digitpair;
                               8515         [ +  + ]:         146865 :         if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
                               8516                 :                :         {
                               8517                 :                :             /* Yes, do it (to base NBASE^2) */
 8205 tgl@sss.pgh.pa.us        8518                 :             15 :             carry = 0;
  387 dean.a.rasheed@gmail     8519         [ +  + ]:          59982 :             for (i = res_ndigitpairs - 1; i >= 0; i--)
                               8520                 :                :             {
 8205 tgl@sss.pgh.pa.us        8521                 :          59967 :                 newdig = dig[i] + carry;
  387 dean.a.rasheed@gmail     8522         [ +  + ]:          59967 :                 if (newdig >= NBASE_SQR)
                               8523                 :                :                 {
                               8524                 :          57621 :                     carry = newdig / NBASE_SQR;
                               8525                 :          57621 :                     newdig -= carry * NBASE_SQR;
                               8526                 :                :                 }
                               8527                 :                :                 else
 8205 tgl@sss.pgh.pa.us        8528                 :           2346 :                     carry = 0;
                               8529                 :          59967 :                 dig[i] = newdig;
                               8530                 :                :             }
                               8531         [ -  + ]:             15 :             Assert(carry == 0);
                               8532                 :                :             /* Reset maxdig to indicate new worst-case */
  387 dean.a.rasheed@gmail     8533                 :             15 :             maxdig = 1 + var1digitpair;
                               8534                 :                :         }
                               8535                 :                : 
                               8536                 :                :         /* Multiply and add */
                               8537                 :         146865 :         i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
                               8538                 :         146865 :         dig_i1_off = &dig[i1 + pair_offset];
                               8539                 :                : 
                               8540         [ +  + ]:       62023923 :         for (i2 = 0; i2 < i2limit; i2++)
                               8541                 :       61877058 :             dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
                               8542                 :                :     }
                               8543                 :                : 
                               8544                 :                :     /*
                               8545                 :                :      * Now we do a final carry propagation pass to normalize back to base
                               8546                 :                :      * NBASE^2, and construct the base-NBASE result digits.  Note that this is
                               8547                 :                :      * still done at full precision w/guard digits.
                               8548                 :                :      */
 8205 tgl@sss.pgh.pa.us        8549                 :          14232 :     alloc_var(result, res_ndigits);
                               8550                 :          14232 :     res_digits = result->digits;
                               8551                 :          14232 :     carry = 0;
  387 dean.a.rasheed@gmail     8552         [ +  + ]:        1441461 :     for (i = res_ndigitpairs - 1; i >= 0; i--)
                               8553                 :                :     {
 8205 tgl@sss.pgh.pa.us        8554                 :        1427229 :         newdig = dig[i] + carry;
  387 dean.a.rasheed@gmail     8555         [ +  + ]:        1427229 :         if (newdig >= NBASE_SQR)
                               8556                 :                :         {
                               8557                 :         203457 :             carry = newdig / NBASE_SQR;
                               8558                 :         203457 :             newdig -= carry * NBASE_SQR;
                               8559                 :                :         }
                               8560                 :                :         else
 8205 tgl@sss.pgh.pa.us        8561                 :        1223772 :             carry = 0;
  387 dean.a.rasheed@gmail     8562                 :        1427229 :         res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
                               8563                 :        1427229 :         res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
                               8564                 :                :     }
 8205 tgl@sss.pgh.pa.us        8565         [ -  + ]:          14232 :     Assert(carry == 0);
                               8566                 :                : 
                               8567                 :          14232 :     pfree(dig);
                               8568                 :                : 
                               8569                 :                :     /*
                               8570                 :                :      * Finally, round the result to the requested precision.
                               8571                 :                :      */
 9601 bruce@momjian.us         8572                 :          14232 :     result->weight = res_weight;
                               8573                 :          14232 :     result->sign = res_sign;
                               8574                 :                : 
                               8575                 :                :     /* Round to target rscale (and set result->dscale) */
 8205 tgl@sss.pgh.pa.us        8576                 :          14232 :     round_var(result, rscale);
                               8577                 :                : 
                               8578                 :                :     /* Strip leading and trailing zeroes */
                               8579                 :          14232 :     strip_var(result);
                               8580                 :                : }
                               8581                 :                : 
                               8582                 :                : 
                               8583                 :                : /*
                               8584                 :                :  * mul_var_short() -
                               8585                 :                :  *
                               8586                 :                :  *  Special-case multiplication function used when var1 has 1-6 digits, var2
                               8587                 :                :  *  has at least as many digits as var1, and the exact product var1 * var2 is
                               8588                 :                :  *  requested.
                               8589                 :                :  */
                               8590                 :                : static void
  424 dean.a.rasheed@gmail     8591                 :         579176 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
                               8592                 :                :               NumericVar *result)
                               8593                 :                : {
                               8594                 :         579176 :     int         var1ndigits = var1->ndigits;
                               8595                 :         579176 :     int         var2ndigits = var2->ndigits;
                               8596                 :         579176 :     NumericDigit *var1digits = var1->digits;
                               8597                 :         579176 :     NumericDigit *var2digits = var2->digits;
                               8598                 :                :     int         res_sign;
                               8599                 :                :     int         res_weight;
                               8600                 :                :     int         res_ndigits;
                               8601                 :                :     NumericDigit *res_buf;
                               8602                 :                :     NumericDigit *res_digits;
  376                          8603                 :         579176 :     uint32      carry = 0;
                               8604                 :                :     uint32      term;
                               8605                 :                : 
                               8606                 :                :     /* Check preconditions */
  424                          8607         [ -  + ]:         579176 :     Assert(var1ndigits >= 1);
  387                          8608         [ -  + ]:         579176 :     Assert(var1ndigits <= 6);
  424                          8609         [ -  + ]:         579176 :     Assert(var2ndigits >= var1ndigits);
                               8610                 :                : 
                               8611                 :                :     /*
                               8612                 :                :      * Determine the result sign, weight, and number of digits to calculate.
                               8613                 :                :      * The weight figured here is correct if the product has no leading zero
                               8614                 :                :      * digits; otherwise strip_var() will fix things up.  Note that, unlike
                               8615                 :                :      * mul_var(), we do not need to allocate an extra output digit, because we
                               8616                 :                :      * are not rounding here.
                               8617                 :                :      */
                               8618         [ +  + ]:         579176 :     if (var1->sign == var2->sign)
                               8619                 :         578580 :         res_sign = NUMERIC_POS;
                               8620                 :                :     else
                               8621                 :            596 :         res_sign = NUMERIC_NEG;
                               8622                 :         579176 :     res_weight = var1->weight + var2->weight + 1;
                               8623                 :         579176 :     res_ndigits = var1ndigits + var2ndigits;
                               8624                 :                : 
                               8625                 :                :     /* Allocate result digit array */
                               8626                 :         579176 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                               8627                 :         579176 :     res_buf[0] = 0;             /* spare digit for later rounding */
                               8628                 :         579176 :     res_digits = res_buf + 1;
                               8629                 :                : 
                               8630                 :                :     /*
                               8631                 :                :      * Compute the result digits in reverse, in one pass, propagating the
                               8632                 :                :      * carry up as we go.  The i'th result digit consists of the sum of the
                               8633                 :                :      * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
                               8634                 :                :      */
                               8635                 :                : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
                               8636                 :                : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
                               8637                 :                : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
                               8638                 :                : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
                               8639                 :                : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
                               8640                 :                : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
                               8641                 :                : 
                               8642   [ +  +  +  +  :         579176 :     switch (var1ndigits)
                                           +  +  - ]
                               8643                 :                :     {
                               8644                 :         576323 :         case 1:
                               8645                 :                :             /* ---------
                               8646                 :                :              * 1-digit case:
                               8647                 :                :              *      var1ndigits = 1
                               8648                 :                :              *      var2ndigits >= 1
                               8649                 :                :              *      res_ndigits = var2ndigits + 1
                               8650                 :                :              * ----------
                               8651                 :                :              */
  387                          8652         [ +  + ]:        1802512 :             for (int i = var2ndigits - 1; i >= 0; i--)
                               8653                 :                :             {
                               8654                 :        1226189 :                 term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
  424                          8655                 :        1226189 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
                               8656                 :        1226189 :                 carry = term / NBASE;
                               8657                 :                :             }
                               8658                 :         576323 :             res_digits[0] = (NumericDigit) carry;
                               8659                 :         576323 :             break;
                               8660                 :                : 
                               8661                 :            378 :         case 2:
                               8662                 :                :             /* ---------
                               8663                 :                :              * 2-digit case:
                               8664                 :                :              *      var1ndigits = 2
                               8665                 :                :              *      var2ndigits >= 2
                               8666                 :                :              *      res_ndigits = var2ndigits + 2
                               8667                 :                :              * ----------
                               8668                 :                :              */
                               8669                 :                :             /* last result digit and carry */
  387                          8670                 :            378 :             term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
  424                          8671                 :            378 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
                               8672                 :            378 :             carry = term / NBASE;
                               8673                 :                : 
                               8674                 :                :             /* remaining digits, except for the first two */
  387                          8675         [ +  + ]:           1152 :             for (int i = var2ndigits - 1; i >= 1; i--)
                               8676                 :                :             {
                               8677                 :            774 :                 term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
  424                          8678                 :            774 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
                               8679                 :            774 :                 carry = term / NBASE;
                               8680                 :                :             }
                               8681                 :            378 :             break;
                               8682                 :                : 
                               8683                 :            102 :         case 3:
                               8684                 :                :             /* ---------
                               8685                 :                :              * 3-digit case:
                               8686                 :                :              *      var1ndigits = 3
                               8687                 :                :              *      var2ndigits >= 3
                               8688                 :                :              *      res_ndigits = var2ndigits + 3
                               8689                 :                :              * ----------
                               8690                 :                :              */
                               8691                 :                :             /* last two result digits */
  387                          8692                 :            102 :             term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
  424                          8693                 :            102 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
                               8694                 :            102 :             carry = term / NBASE;
                               8695                 :                : 
  387                          8696                 :            102 :             term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
  424                          8697                 :            102 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
                               8698                 :            102 :             carry = term / NBASE;
                               8699                 :                : 
                               8700                 :                :             /* remaining digits, except for the first three */
  387                          8701         [ +  + ]:            273 :             for (int i = var2ndigits - 1; i >= 2; i--)
                               8702                 :                :             {
                               8703                 :            171 :                 term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
  424                          8704                 :            171 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
                               8705                 :            171 :                 carry = term / NBASE;
                               8706                 :                :             }
                               8707                 :            102 :             break;
                               8708                 :                : 
                               8709                 :           2019 :         case 4:
                               8710                 :                :             /* ---------
                               8711                 :                :              * 4-digit case:
                               8712                 :                :              *      var1ndigits = 4
                               8713                 :                :              *      var2ndigits >= 4
                               8714                 :                :              *      res_ndigits = var2ndigits + 4
                               8715                 :                :              * ----------
                               8716                 :                :              */
                               8717                 :                :             /* last three result digits */
  387                          8718                 :           2019 :             term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
  424                          8719                 :           2019 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
                               8720                 :           2019 :             carry = term / NBASE;
                               8721                 :                : 
  387                          8722                 :           2019 :             term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
  424                          8723                 :           2019 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
                               8724                 :           2019 :             carry = term / NBASE;
                               8725                 :                : 
  387                          8726                 :           2019 :             term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
  424                          8727                 :           2019 :             res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
                               8728                 :           2019 :             carry = term / NBASE;
                               8729                 :                : 
                               8730                 :                :             /* remaining digits, except for the first four */
  387                          8731         [ +  + ]:           5634 :             for (int i = var2ndigits - 1; i >= 3; i--)
                               8732                 :                :             {
                               8733                 :           3615 :                 term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
  424                          8734                 :           3615 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
                               8735                 :           3615 :                 carry = term / NBASE;
                               8736                 :                :             }
  387                          8737                 :           2019 :             break;
                               8738                 :                : 
                               8739                 :             57 :         case 5:
                               8740                 :                :             /* ---------
                               8741                 :                :              * 5-digit case:
                               8742                 :                :              *      var1ndigits = 5
                               8743                 :                :              *      var2ndigits >= 5
                               8744                 :                :              *      res_ndigits = var2ndigits + 5
                               8745                 :                :              * ----------
                               8746                 :                :              */
                               8747                 :                :             /* last four result digits */
                               8748                 :             57 :             term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
                               8749                 :             57 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
  424                          8750                 :             57 :             carry = term / NBASE;
                               8751                 :                : 
  387                          8752                 :             57 :             term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
                               8753                 :             57 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
                               8754                 :             57 :             carry = term / NBASE;
                               8755                 :                : 
                               8756                 :             57 :             term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
                               8757                 :             57 :             res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
  424                          8758                 :             57 :             carry = term / NBASE;
                               8759                 :                : 
  387                          8760                 :             57 :             term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
                               8761                 :             57 :             res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
                               8762                 :             57 :             carry = term / NBASE;
                               8763                 :                : 
                               8764                 :                :             /* remaining digits, except for the first five */
                               8765         [ +  + ]:            150 :             for (int i = var2ndigits - 1; i >= 4; i--)
                               8766                 :                :             {
                               8767                 :             93 :                 term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
                               8768                 :             93 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
                               8769                 :             93 :                 carry = term / NBASE;
                               8770                 :                :             }
                               8771                 :             57 :             break;
                               8772                 :                : 
                               8773                 :            297 :         case 6:
                               8774                 :                :             /* ---------
                               8775                 :                :              * 6-digit case:
                               8776                 :                :              *      var1ndigits = 6
                               8777                 :                :              *      var2ndigits >= 6
                               8778                 :                :              *      res_ndigits = var2ndigits + 6
                               8779                 :                :              * ----------
                               8780                 :                :              */
                               8781                 :                :             /* last five result digits */
                               8782                 :            297 :             term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
                               8783                 :            297 :             res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
                               8784                 :            297 :             carry = term / NBASE;
                               8785                 :                : 
                               8786                 :            297 :             term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
                               8787                 :            297 :             res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
                               8788                 :            297 :             carry = term / NBASE;
                               8789                 :                : 
                               8790                 :            297 :             term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
                               8791                 :            297 :             res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
                               8792                 :            297 :             carry = term / NBASE;
                               8793                 :                : 
                               8794                 :            297 :             term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
                               8795                 :            297 :             res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
                               8796                 :            297 :             carry = term / NBASE;
                               8797                 :                : 
                               8798                 :            297 :             term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
                               8799                 :            297 :             res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
                               8800                 :            297 :             carry = term / NBASE;
                               8801                 :                : 
                               8802                 :                :             /* remaining digits, except for the first six */
                               8803         [ +  + ]:            828 :             for (int i = var2ndigits - 1; i >= 5; i--)
                               8804                 :                :             {
                               8805                 :            531 :                 term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
                               8806                 :            531 :                 res_digits[i + 1] = (NumericDigit) (term % NBASE);
                               8807                 :            531 :                 carry = term / NBASE;
                               8808                 :                :             }
                               8809                 :            297 :             break;
                               8810                 :                :     }
                               8811                 :                : 
                               8812                 :                :     /*
                               8813                 :                :      * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
                               8814                 :                :      * significant result digits.
                               8815                 :                :      */
                               8816   [ +  +  +  +  :         579176 :     switch (var1ndigits)
                                              +  + ]
                               8817                 :                :     {
                               8818                 :            297 :         case 6:
                               8819                 :            297 :             term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
                               8820                 :            297 :             res_digits[5] = (NumericDigit) (term % NBASE);
                               8821                 :            297 :             carry = term / NBASE;
                               8822                 :                :             /* FALLTHROUGH */
                               8823                 :            354 :         case 5:
                               8824                 :            354 :             term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
                               8825                 :            354 :             res_digits[4] = (NumericDigit) (term % NBASE);
                               8826                 :            354 :             carry = term / NBASE;
                               8827                 :                :             /* FALLTHROUGH */
                               8828                 :           2373 :         case 4:
                               8829                 :           2373 :             term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
                               8830                 :           2373 :             res_digits[3] = (NumericDigit) (term % NBASE);
                               8831                 :           2373 :             carry = term / NBASE;
                               8832                 :                :             /* FALLTHROUGH */
                               8833                 :           2475 :         case 3:
                               8834                 :           2475 :             term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
                               8835                 :           2475 :             res_digits[2] = (NumericDigit) (term % NBASE);
                               8836                 :           2475 :             carry = term / NBASE;
                               8837                 :                :             /* FALLTHROUGH */
                               8838                 :           2853 :         case 2:
                               8839                 :           2853 :             term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
  424                          8840                 :           2853 :             res_digits[1] = (NumericDigit) (term % NBASE);
                               8841                 :           2853 :             res_digits[0] = (NumericDigit) (term / NBASE);
                               8842                 :           2853 :             break;
                               8843                 :                :     }
                               8844                 :                : 
                               8845                 :                :     /* Store the product in result */
                               8846         [ +  + ]:         579176 :     digitbuf_free(result->buf);
                               8847                 :         579176 :     result->ndigits = res_ndigits;
                               8848                 :         579176 :     result->buf = res_buf;
                               8849                 :         579176 :     result->digits = res_digits;
                               8850                 :         579176 :     result->weight = res_weight;
                               8851                 :         579176 :     result->sign = res_sign;
                               8852                 :         579176 :     result->dscale = var1->dscale + var2->dscale;
                               8853                 :                : 
                               8854                 :                :     /* Strip leading and trailing zeroes */
                               8855                 :         579176 :     strip_var(result);
                               8856                 :         579176 : }
                               8857                 :                : 
                               8858                 :                : 
                               8859                 :                : /*
                               8860                 :                :  * div_var() -
                               8861                 :                :  *
                               8862                 :                :  *  Compute the quotient var1 / var2 to rscale fractional digits.
                               8863                 :                :  *
                               8864                 :                :  *  If "round" is true, the result is rounded at the rscale'th digit; if
                               8865                 :                :  *  false, it is truncated (towards zero) at that digit.
                               8866                 :                :  *
                               8867                 :                :  *  If "exact" is true, the exact result is computed to the specified rscale;
                               8868                 :                :  *  if false, successive quotient digits are approximated up to rscale plus
                               8869                 :                :  *  DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to
                               8870                 :                :  *  the right of that, before rounding or truncating to the specified rscale.
                               8871                 :                :  *  This can be significantly faster, and usually gives the same result as the
                               8872                 :                :  *  exact computation, but it may occasionally be off by one in the final
                               8873                 :                :  *  digit, if contributions from the ignored digits would have propagated
                               8874                 :                :  *  through the guard digits.  This is good enough for the transcendental
                               8875                 :                :  *  functions, where small errors are acceptable.
                               8876                 :                :  */
                               8877                 :                : static void
 2918 andres@anarazel.de       8878                 :         285535 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
                               8879                 :                :         int rscale, bool round, bool exact)
                               8880                 :                : {
  337 dean.a.rasheed@gmail     8881                 :         285535 :     int         var1ndigits = var1->ndigits;
                               8882                 :         285535 :     int         var2ndigits = var2->ndigits;
                               8883                 :                :     int         res_sign;
                               8884                 :                :     int         res_weight;
                               8885                 :                :     int         res_ndigits;
                               8886                 :                :     int         var1ndigitpairs;
                               8887                 :                :     int         var2ndigitpairs;
                               8888                 :                :     int         res_ndigitpairs;
                               8889                 :                :     int         div_ndigitpairs;
                               8890                 :                :     int64      *dividend;
                               8891                 :                :     int32      *divisor;
                               8892                 :                :     double      fdivisor,
                               8893                 :                :                 fdivisorinverse,
                               8894                 :                :                 fdividend,
                               8895                 :                :                 fquotient;
                               8896                 :                :     int64       maxdiv;
                               8897                 :                :     int         qi;
                               8898                 :                :     int32       qdigit;
                               8899                 :                :     int64       carry;
                               8900                 :                :     int64       newdig;
                               8901                 :                :     int64      *remainder;
                               8902                 :                :     NumericDigit *res_digits;
                               8903                 :                :     int         i;
                               8904                 :                : 
                               8905                 :                :     /*
                               8906                 :                :      * First of all division by zero check; we must not be handed an
                               8907                 :                :      * unnormalized divisor.
                               8908                 :                :      */
 6364 tgl@sss.pgh.pa.us        8909   [ +  +  -  + ]:         285535 :     if (var2ndigits == 0 || var2->digits[0] == 0)
                               8910         [ +  - ]:              6 :         ereport(ERROR,
                               8911                 :                :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
                               8912                 :                :                  errmsg("division by zero")));
                               8913                 :                : 
                               8914                 :                :     /*
                               8915                 :                :      * If the divisor has just one or two digits, delegate to div_var_int(),
                               8916                 :                :      * which uses fast short division.
                               8917                 :                :      *
                               8918                 :                :      * Similarly, on platforms with 128-bit integer support, delegate to
                               8919                 :                :      * div_var_int64() for divisors with three or four digits.
                               8920                 :                :      */
 1287 dean.a.rasheed@gmail     8921         [ +  + ]:         285529 :     if (var2ndigits <= 2)
                               8922                 :                :     {
                               8923                 :                :         int         idivisor;
                               8924                 :                :         int         idivisor_weight;
                               8925                 :                : 
                               8926                 :         282526 :         idivisor = var2->digits[0];
                               8927                 :         282526 :         idivisor_weight = var2->weight;
                               8928         [ +  + ]:         282526 :         if (var2ndigits == 2)
                               8929                 :                :         {
                               8930                 :           1917 :             idivisor = idivisor * NBASE + var2->digits[1];
                               8931                 :           1917 :             idivisor_weight--;
                               8932                 :                :         }
                               8933         [ +  + ]:         282526 :         if (var2->sign == NUMERIC_NEG)
                               8934                 :            327 :             idivisor = -idivisor;
                               8935                 :                : 
                               8936                 :         282526 :         div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
                               8937                 :         282526 :         return;
                               8938                 :                :     }
                               8939                 :                : #ifdef HAVE_INT128
  957                          8940         [ +  + ]:           3003 :     if (var2ndigits <= 4)
                               8941                 :                :     {
                               8942                 :                :         int64       idivisor;
                               8943                 :                :         int         idivisor_weight;
                               8944                 :                : 
                               8945                 :            264 :         idivisor = var2->digits[0];
                               8946                 :            264 :         idivisor_weight = var2->weight;
                               8947         [ +  + ]:            984 :         for (i = 1; i < var2ndigits; i++)
                               8948                 :                :         {
                               8949                 :            720 :             idivisor = idivisor * NBASE + var2->digits[i];
                               8950                 :            720 :             idivisor_weight--;
                               8951                 :                :         }
                               8952         [ +  + ]:            264 :         if (var2->sign == NUMERIC_NEG)
                               8953                 :             60 :             idivisor = -idivisor;
                               8954                 :                : 
                               8955                 :            264 :         div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
                               8956                 :            264 :         return;
                               8957                 :                :     }
                               8958                 :                : #endif
                               8959                 :                : 
                               8960                 :                :     /*
                               8961                 :                :      * Otherwise, perform full long division.
                               8962                 :                :      */
                               8963                 :                : 
                               8964                 :                :     /* Result zero check */
 6364 tgl@sss.pgh.pa.us        8965         [ +  + ]:           2739 :     if (var1ndigits == 0)
                               8966                 :                :     {
                               8967                 :             18 :         zero_var(result);
                               8968                 :             18 :         result->dscale = rscale;
                               8969                 :             18 :         return;
                               8970                 :                :     }
                               8971                 :                : 
                               8972                 :                :     /*
                               8973                 :                :      * The approximate computation can be significantly faster than the exact
                               8974                 :                :      * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
                               8975                 :                :      * shorter below.  However, that comes with the tradeoff of computing
                               8976                 :                :      * DIV_GUARD_DIGITS extra base-NBASE result digits.  Ignoring all other
                               8977                 :                :      * overheads, that suggests that, in theory, the approximate computation
                               8978                 :                :      * will only be faster than the exact one when var2ndigits is greater than
                               8979                 :                :      * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
                               8980                 :                :      *
                               8981                 :                :      * Thus, we're better off doing an exact computation when var2 is shorter
                               8982                 :                :      * than this.  Empirically, it has been found that the exact threshold is
                               8983                 :                :      * a little higher, due to other overheads in the outer division loop.
                               8984                 :                :      */
  337 dean.a.rasheed@gmail     8985         [ +  + ]:           2721 :     if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
                               8986                 :           1854 :         exact = true;
                               8987                 :                : 
                               8988                 :                :     /*
                               8989                 :                :      * Determine the result sign, weight and number of digits to calculate.
                               8990                 :                :      * The weight figured here is correct if the emitted quotient has no
                               8991                 :                :      * leading zero digits; otherwise strip_var() will fix things up.
                               8992                 :                :      */
 6364 tgl@sss.pgh.pa.us        8993         [ +  + ]:           2721 :     if (var1->sign == var2->sign)
                               8994                 :           2655 :         res_sign = NUMERIC_POS;
                               8995                 :                :     else
                               8996                 :             66 :         res_sign = NUMERIC_NEG;
  337 dean.a.rasheed@gmail     8997                 :           2721 :     res_weight = var1->weight - var2->weight + 1;
                               8998                 :                :     /* The number of accurate result digits we need to produce: */
 6364 tgl@sss.pgh.pa.us        8999                 :           2721 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               9000                 :                :     /* ... but always at least 1 */
                               9001                 :           2721 :     res_ndigits = Max(res_ndigits, 1);
                               9002                 :                :     /* If rounding needed, figure one more digit to ensure correct result */
                               9003         [ +  + ]:           2721 :     if (round)
                               9004                 :            453 :         res_ndigits++;
                               9005                 :                :     /* Add guard digits for roundoff error when producing approx result */
  337 dean.a.rasheed@gmail     9006         [ +  + ]:           2721 :     if (!exact)
                               9007                 :            861 :         res_ndigits += DIV_GUARD_DIGITS;
                               9008                 :                : 
                               9009                 :                :     /*
                               9010                 :                :      * The computation itself is done using base-NBASE^2 arithmetic, so we
                               9011                 :                :      * actually process the input digits in pairs, producing a base-NBASE^2
                               9012                 :                :      * intermediate result.  This significantly improves performance, since
                               9013                 :                :      * the computation is O(N^2) in the number of input digits, and working in
                               9014                 :                :      * base NBASE^2 effectively halves "N".
                               9015                 :                :      */
                               9016                 :           2721 :     var1ndigitpairs = (var1ndigits + 1) / 2;
                               9017                 :           2721 :     var2ndigitpairs = (var2ndigits + 1) / 2;
                               9018                 :           2721 :     res_ndigitpairs = (res_ndigits + 1) / 2;
                               9019                 :           2721 :     res_ndigits = 2 * res_ndigitpairs;
                               9020                 :                : 
                               9021                 :                :     /*
                               9022                 :                :      * We do the arithmetic in an array "dividend[]" of signed 64-bit
                               9023                 :                :      * integers.  Since PG_INT64_MAX is much larger than NBASE^4, this gives
                               9024                 :                :      * us a lot of headroom to avoid normalizing carries immediately.
                               9025                 :                :      *
                               9026                 :                :      * When performing an exact computation, the working dividend requires
                               9027                 :                :      * res_ndigitpairs + var2ndigitpairs digits.  If var1 is larger than that,
                               9028                 :                :      * the extra digits do not contribute to the result, and are ignored.
                               9029                 :                :      *
                               9030                 :                :      * When performing an approximate computation, the working dividend only
                               9031                 :                :      * requires res_ndigitpairs digits (which includes the extra guard
                               9032                 :                :      * digits).  All input digits beyond that are ignored.
                               9033                 :                :      */
                               9034         [ +  + ]:           2721 :     if (exact)
                               9035                 :                :     {
                               9036                 :           1860 :         div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
                               9037                 :           1860 :         var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
                               9038                 :                :     }
                               9039                 :                :     else
                               9040                 :                :     {
                               9041                 :            861 :         div_ndigitpairs = res_ndigitpairs;
                               9042                 :            861 :         var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
                               9043                 :            861 :         var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
                               9044                 :                :     }
                               9045                 :                : 
                               9046                 :                :     /*
                               9047                 :                :      * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
                               9048                 :                :      * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
                               9049                 :                :      *
                               9050                 :                :      * For convenience, we allocate one extra dividend digit, which is set to
                               9051                 :                :      * zero and not counted in div_ndigitpairs, so that the main loop below
                               9052                 :                :      * can safely read and write the (qi+1)'th digit in the approximate case.
                               9053                 :                :      */
                               9054                 :           2721 :     dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
                               9055                 :                :                                 var2ndigitpairs * sizeof(int32));
                               9056                 :           2721 :     divisor = (int32 *) (dividend + div_ndigitpairs + 1);
                               9057                 :                : 
                               9058                 :                :     /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
                               9059         [ +  + ]:          24729 :     for (i = 0; i < var1ndigitpairs - 1; i++)
                               9060                 :          22008 :         dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
                               9061                 :                : 
                               9062         [ +  + ]:           2721 :     if (2 * i + 1 < var1ndigits)
                               9063                 :           1641 :         dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
                               9064                 :                :     else
                               9065                 :           1080 :         dividend[i] = var1->digits[2 * i] * NBASE;
                               9066                 :                : 
                               9067                 :           2721 :     memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
                               9068                 :                : 
                               9069                 :                :     /* load var2 into divisor[0 .. var2ndigitpairs-1] */
                               9070         [ +  + ]:          19920 :     for (i = 0; i < var2ndigitpairs - 1; i++)
                               9071                 :          17199 :         divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
                               9072                 :                : 
                               9073         [ +  + ]:           2721 :     if (2 * i + 1 < var2ndigits)
                               9074                 :           1461 :         divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
                               9075                 :                :     else
                               9076                 :           1260 :         divisor[i] = var2->digits[2 * i] * NBASE;
                               9077                 :                : 
                               9078                 :                :     /*
                               9079                 :                :      * We estimate each quotient digit using floating-point arithmetic, taking
                               9080                 :                :      * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
                               9081                 :                :      * This must be float to avoid overflow.
                               9082                 :                :      *
                               9083                 :                :      * Since the floating-point dividend and divisor use 4 base-NBASE input
                               9084                 :                :      * digits, they include roughly 40-53 bits of information from their
                               9085                 :                :      * respective inputs (assuming NBASE is 10000), which fits well in IEEE
                               9086                 :                :      * double-precision variables.  The relative error in the floating-point
                               9087                 :                :      * quotient digit will then be less than around 2/NBASE^3, so the
                               9088                 :                :      * estimated base-NBASE^2 quotient digit will typically be correct, and
                               9089                 :                :      * should not be off by more than one from the correct value.
                               9090                 :                :      */
                               9091                 :           2721 :     fdivisor = (double) divisor[0] * NBASE_SQR;
                               9092         [ +  - ]:           2721 :     if (var2ndigitpairs > 1)
                               9093                 :           2721 :         fdivisor += (double) divisor[1];
 8205 tgl@sss.pgh.pa.us        9094                 :           2721 :     fdivisorinverse = 1.0 / fdivisor;
                               9095                 :                : 
                               9096                 :                :     /*
                               9097                 :                :      * maxdiv tracks the maximum possible absolute value of any dividend[]
                               9098                 :                :      * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
                               9099                 :                :      * propagate carries.  Furthermore, we need to ensure that overflow
                               9100                 :                :      * doesn't occur during the carry propagation passes either.  The carry
                               9101                 :                :      * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
                               9102                 :                :      * so really we must normalize when digits threaten to exceed PG_INT64_MAX
                               9103                 :                :      * - PG_INT64_MAX/NBASE^2 - 1.
                               9104                 :                :      *
                               9105                 :                :      * To avoid overflow in maxdiv itself, it represents the max absolute
                               9106                 :                :      * value divided by NBASE^2-1, i.e., at the top of the loop it is known
                               9107                 :                :      * that no dividend[] entry has an absolute value exceeding maxdiv *
                               9108                 :                :      * (NBASE^2-1).
                               9109                 :                :      *
                               9110                 :                :      * Actually, though, that holds good only for dividend[] entries after
                               9111                 :                :      * dividend[qi]; the adjustment done at the bottom of the loop may cause
                               9112                 :                :      * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
                               9113                 :                :      * the next iteration is beyond the limit.  This does not cause problems,
                               9114                 :                :      * as explained below.
                               9115                 :                :      */
                               9116                 :           2721 :     maxdiv = 1;
                               9117                 :                : 
                               9118                 :                :     /*
                               9119                 :                :      * Outer loop computes next quotient digit, which goes in dividend[qi].
                               9120                 :                :      */
  337 dean.a.rasheed@gmail     9121         [ +  + ]:          24771 :     for (qi = 0; qi < res_ndigitpairs; qi++)
                               9122                 :                :     {
                               9123                 :                :         /* Approximate the current dividend value */
                               9124                 :          22050 :         fdividend = (double) dividend[qi] * NBASE_SQR;
                               9125                 :          22050 :         fdividend += (double) dividend[qi + 1];
                               9126                 :                : 
                               9127                 :                :         /* Compute the (approximate) quotient digit */
 8205 tgl@sss.pgh.pa.us        9128                 :          22050 :         fquotient = fdividend * fdivisorinverse;
  337 dean.a.rasheed@gmail     9129         [ +  + ]:          22050 :         qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
                               9130                 :              3 :             (((int32) fquotient) - 1);  /* truncate towards -infinity */
                               9131                 :                : 
 8205 tgl@sss.pgh.pa.us        9132         [ +  + ]:          22050 :         if (qdigit != 0)
                               9133                 :                :         {
                               9134                 :                :             /* Do we need to normalize now? */
  337 dean.a.rasheed@gmail     9135                 :          20253 :             maxdiv += i64abs(qdigit);
                               9136         [ +  + ]:          20253 :             if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
                               9137                 :                :             {
                               9138                 :                :                 /*
                               9139                 :                :                  * Yes, do it.  Note that if var2ndigitpairs is much smaller
                               9140                 :                :                  * than div_ndigitpairs, we can save a significant amount of
                               9141                 :                :                  * effort here by noting that we only need to normalise those
                               9142                 :                :                  * dividend[] entries touched where prior iterations
                               9143                 :                :                  * subtracted multiples of the divisor.
                               9144                 :                :                  */
 8205 tgl@sss.pgh.pa.us        9145                 :              3 :                 carry = 0;
  337 dean.a.rasheed@gmail     9146         [ +  + ]:           3375 :                 for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
                               9147                 :                :                 {
                               9148                 :           3372 :                     newdig = dividend[i] + carry;
 8205 tgl@sss.pgh.pa.us        9149         [ +  - ]:           3372 :                     if (newdig < 0)
                               9150                 :                :                     {
  337 dean.a.rasheed@gmail     9151                 :           3372 :                         carry = -((-newdig - 1) / NBASE_SQR) - 1;
                               9152                 :           3372 :                         newdig -= carry * NBASE_SQR;
                               9153                 :                :                     }
  337 dean.a.rasheed@gmail     9154         [ #  # ]:UBC           0 :                     else if (newdig >= NBASE_SQR)
                               9155                 :                :                     {
                               9156                 :              0 :                         carry = newdig / NBASE_SQR;
                               9157                 :              0 :                         newdig -= carry * NBASE_SQR;
                               9158                 :                :                     }
                               9159                 :                :                     else
 8205 tgl@sss.pgh.pa.us        9160                 :              0 :                         carry = 0;
  337 dean.a.rasheed@gmail     9161                 :CBC        3372 :                     dividend[i] = newdig;
                               9162                 :                :                 }
                               9163                 :              3 :                 dividend[qi] += carry;
                               9164                 :                : 
                               9165                 :                :                 /*
                               9166                 :                :                  * All the dividend[] digits except possibly dividend[qi] are
                               9167                 :                :                  * now in the range 0..NBASE^2-1.  We do not need to consider
                               9168                 :                :                  * dividend[qi] in the maxdiv value anymore, so we can reset
                               9169                 :                :                  * maxdiv to 1.
                               9170                 :                :                  */
 3573 tgl@sss.pgh.pa.us        9171                 :              3 :                 maxdiv = 1;
                               9172                 :                : 
                               9173                 :                :                 /*
                               9174                 :                :                  * Recompute the quotient digit since new info may have
                               9175                 :                :                  * propagated into the top two dividend digits.
                               9176                 :                :                  */
  337 dean.a.rasheed@gmail     9177                 :              3 :                 fdividend = (double) dividend[qi] * NBASE_SQR;
                               9178                 :              3 :                 fdividend += (double) dividend[qi + 1];
 8205 tgl@sss.pgh.pa.us        9179                 :              3 :                 fquotient = fdividend * fdivisorinverse;
  337 dean.a.rasheed@gmail     9180         [ +  - ]:              3 :                 qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
  337 dean.a.rasheed@gmail     9181                 :UBC           0 :                     (((int32) fquotient) - 1);  /* truncate towards -infinity */
                               9182                 :                : 
  337 dean.a.rasheed@gmail     9183                 :CBC           3 :                 maxdiv += i64abs(qdigit);
                               9184                 :                :             }
                               9185                 :                : 
                               9186                 :                :             /*
                               9187                 :                :              * Subtract off the appropriate multiple of the divisor.
                               9188                 :                :              *
                               9189                 :                :              * The digits beyond dividend[qi] cannot overflow, because we know
                               9190                 :                :              * they will fall within the maxdiv limit.  As for dividend[qi]
                               9191                 :                :              * itself, note that qdigit is approximately trunc(dividend[qi] /
                               9192                 :                :              * divisor[0]), which would make the new value simply dividend[qi]
                               9193                 :                :              * mod divisor[0].  The lower-order terms in qdigit can change
                               9194                 :                :              * this result by not more than about twice PG_INT64_MAX/NBASE^2,
                               9195                 :                :              * so overflow is impossible.
                               9196                 :                :              *
                               9197                 :                :              * This inner loop is the performance bottleneck for division, so
                               9198                 :                :              * code it in the same way as the inner loop of mul_var() so that
                               9199                 :                :              * it can be auto-vectorized.
                               9200                 :                :              */
 8205 tgl@sss.pgh.pa.us        9201         [ +  - ]:          20253 :             if (qdigit != 0)
                               9202                 :                :             {
  337 dean.a.rasheed@gmail     9203                 :          20253 :                 int         istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
                               9204                 :          20253 :                 int64      *dividend_qi = &dividend[qi];
                               9205                 :                : 
 8205 tgl@sss.pgh.pa.us        9206         [ +  + ]:        3930627 :                 for (i = 0; i < istop; i++)
  337 dean.a.rasheed@gmail     9207                 :        3910374 :                     dividend_qi[i] -= (int64) qdigit * divisor[i];
                               9208                 :                :             }
                               9209                 :                :         }
                               9210                 :                : 
                               9211                 :                :         /*
                               9212                 :                :          * The dividend digit we are about to replace might still be nonzero.
                               9213                 :                :          * Fold it into the next digit position.
                               9214                 :                :          *
                               9215                 :                :          * There is no risk of overflow here, although proving that requires
                               9216                 :                :          * some care.  Much as with the argument for dividend[qi] not
                               9217                 :                :          * overflowing, if we consider the first two terms in the numerator
                               9218                 :                :          * and denominator of qdigit, we can see that the final value of
                               9219                 :                :          * dividend[qi + 1] will be approximately a remainder mod
                               9220                 :                :          * (divisor[0]*NBASE^2 + divisor[1]).  Accounting for the lower-order
                               9221                 :                :          * terms is a bit complicated but ends up adding not much more than
                               9222                 :                :          * PG_INT64_MAX/NBASE^2 to the possible range.  Thus, dividend[qi + 1]
                               9223                 :                :          * cannot overflow here, and in its role as dividend[qi] in the next
                               9224                 :                :          * loop iteration, it can't be large enough to cause overflow in the
                               9225                 :                :          * carry propagation step (if any), either.
                               9226                 :                :          *
                               9227                 :                :          * But having said that: dividend[qi] can be more than
                               9228                 :                :          * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
                               9229                 :                :          * dividend[qi] * NBASE^2 *can* overflow.  When that happens, adding
                               9230                 :                :          * it to dividend[qi + 1] will always cause a canceling overflow so
                               9231                 :                :          * that the end result is correct.  We could avoid the intermediate
                               9232                 :                :          * overflow by doing the multiplication and addition using unsigned
                               9233                 :                :          * int64 arithmetic, which is modulo 2^64, but so far there appears no
                               9234                 :                :          * need.
                               9235                 :                :          */
                               9236                 :          22050 :         dividend[qi + 1] += dividend[qi] * NBASE_SQR;
                               9237                 :                : 
                               9238                 :          22050 :         dividend[qi] = qdigit;
                               9239                 :                :     }
                               9240                 :                : 
                               9241                 :                :     /*
                               9242                 :                :      * If an exact result was requested, use the remainder to correct the
                               9243                 :                :      * approximate quotient.  The remainder is in dividend[], immediately
                               9244                 :                :      * after the quotient digits.  Note, however, that although the remainder
                               9245                 :                :      * starts at dividend[qi = res_ndigitpairs], the first digit is the result
                               9246                 :                :      * of folding two remainder digits into one above, and the remainder
                               9247                 :                :      * currently only occupies var2ndigitpairs - 1 digits (the last digit of
                               9248                 :                :      * the working dividend was untouched by the computation above).  Thus we
                               9249                 :                :      * expand the remainder down by one base-NBASE^2 digit when we normalize
                               9250                 :                :      * it, so that it completely fills the last var2ndigitpairs digits of the
                               9251                 :                :      * dividend array.
                               9252                 :                :      */
                               9253         [ +  + ]:           2721 :     if (exact)
                               9254                 :                :     {
                               9255                 :                :         /* Normalize the remainder, expanding it down by one digit */
                               9256                 :           1860 :         remainder = &dividend[qi];
                               9257                 :           1860 :         carry = 0;
                               9258         [ +  + ]:          10107 :         for (i = var2ndigitpairs - 2; i >= 0; i--)
                               9259                 :                :         {
                               9260                 :           8247 :             newdig = remainder[i] + carry;
                               9261         [ +  + ]:           8247 :             if (newdig < 0)
                               9262                 :                :             {
                               9263                 :           6366 :                 carry = -((-newdig - 1) / NBASE_SQR) - 1;
                               9264                 :           6366 :                 newdig -= carry * NBASE_SQR;
                               9265                 :                :             }
                               9266         [ +  + ]:           1881 :             else if (newdig >= NBASE_SQR)
                               9267                 :                :             {
                               9268                 :           1842 :                 carry = newdig / NBASE_SQR;
                               9269                 :           1842 :                 newdig -= carry * NBASE_SQR;
                               9270                 :                :             }
                               9271                 :                :             else
                               9272                 :             39 :                 carry = 0;
                               9273                 :           8247 :             remainder[i + 1] = newdig;
                               9274                 :                :         }
                               9275                 :           1860 :         remainder[0] = carry;
                               9276                 :                : 
                               9277         [ +  + ]:           1860 :         if (remainder[0] < 0)
                               9278                 :                :         {
                               9279                 :                :             /*
                               9280                 :                :              * The remainder is negative, so the approximate quotient is too
                               9281                 :                :              * large.  Correct by reducing the quotient by one and adding the
                               9282                 :                :              * divisor to the remainder until the remainder is positive.  We
                               9283                 :                :              * expect the quotient to be off by at most one, which has been
                               9284                 :                :              * borne out in all testing, but not conclusively proven, so we
                               9285                 :                :              * allow for larger corrections, just in case.
                               9286                 :                :              */
                               9287                 :                :             do
                               9288                 :                :             {
                               9289                 :                :                 /* Add the divisor to the remainder */
                               9290                 :              3 :                 carry = 0;
                               9291         [ +  + ]:             39 :                 for (i = var2ndigitpairs - 1; i > 0; i--)
                               9292                 :                :                 {
                               9293                 :             36 :                     newdig = remainder[i] + divisor[i] + carry;
                               9294         [ -  + ]:             36 :                     if (newdig >= NBASE_SQR)
                               9295                 :                :                     {
  337 dean.a.rasheed@gmail     9296                 :UBC           0 :                         remainder[i] = newdig - NBASE_SQR;
                               9297                 :              0 :                         carry = 1;
                               9298                 :                :                     }
                               9299                 :                :                     else
                               9300                 :                :                     {
  337 dean.a.rasheed@gmail     9301                 :CBC          36 :                         remainder[i] = newdig;
                               9302                 :             36 :                         carry = 0;
                               9303                 :                :                     }
                               9304                 :                :                 }
                               9305                 :              3 :                 remainder[0] += divisor[0] + carry;
                               9306                 :                : 
                               9307                 :                :                 /* Subtract 1 from the quotient (propagating carries later) */
                               9308                 :              3 :                 dividend[qi - 1]--;
                               9309                 :                : 
                               9310         [ -  + ]:              3 :             } while (remainder[0] < 0);
                               9311                 :                :         }
                               9312                 :                :         else
                               9313                 :                :         {
                               9314                 :                :             /*
                               9315                 :                :              * The remainder is nonnegative.  If it's greater than or equal to
                               9316                 :                :              * the divisor, then the approximate quotient is too small and
                               9317                 :                :              * must be corrected.  As above, we don't expect to have to apply
                               9318                 :                :              * more than one correction, but allow for it just in case.
                               9319                 :                :              */
                               9320                 :                :             while (true)
                               9321                 :              3 :             {
                               9322                 :           1860 :                 bool        less = false;
                               9323                 :                : 
                               9324                 :                :                 /* Is remainder < divisor? */
                               9325         [ +  + ]:           1869 :                 for (i = 0; i < var2ndigitpairs; i++)
                               9326                 :                :                 {
                               9327         [ +  + ]:           1866 :                     if (remainder[i] < divisor[i])
                               9328                 :                :                     {
                               9329                 :           1857 :                         less = true;
                               9330                 :           1857 :                         break;
                               9331                 :                :                     }
                               9332         [ -  + ]:              9 :                     if (remainder[i] > divisor[i])
  337 dean.a.rasheed@gmail     9333                 :UBC           0 :                         break;  /* remainder > divisor */
                               9334                 :                :                 }
  337 dean.a.rasheed@gmail     9335         [ +  + ]:CBC        1860 :                 if (less)
                               9336                 :           1857 :                     break;      /* quotient is correct */
                               9337                 :                : 
                               9338                 :                :                 /* Subtract the divisor from the remainder */
                               9339                 :              3 :                 carry = 0;
                               9340         [ +  + ]:              9 :                 for (i = var2ndigitpairs - 1; i > 0; i--)
                               9341                 :                :                 {
                               9342                 :              6 :                     newdig = remainder[i] - divisor[i] + carry;
                               9343         [ -  + ]:              6 :                     if (newdig < 0)
                               9344                 :                :                     {
  337 dean.a.rasheed@gmail     9345                 :UBC           0 :                         remainder[i] = newdig + NBASE_SQR;
                               9346                 :              0 :                         carry = -1;
                               9347                 :                :                     }
                               9348                 :                :                     else
                               9349                 :                :                     {
  337 dean.a.rasheed@gmail     9350                 :CBC           6 :                         remainder[i] = newdig;
                               9351                 :              6 :                         carry = 0;
                               9352                 :                :                     }
                               9353                 :                :                 }
                               9354                 :              3 :                 remainder[0] = remainder[0] - divisor[0] + carry;
                               9355                 :                : 
                               9356                 :                :                 /* Add 1 to the quotient (propagating carries later) */
                               9357                 :              3 :                 dividend[qi - 1]++;
                               9358                 :                :             }
                               9359                 :                :         }
                               9360                 :                :     }
                               9361                 :                : 
                               9362                 :                :     /*
                               9363                 :                :      * Because the quotient digits were estimates that might have been off by
                               9364                 :                :      * one (and we didn't bother propagating carries when adjusting the
                               9365                 :                :      * quotient above), some quotient digits might be out of range, so do a
                               9366                 :                :      * final carry propagation pass to normalize back to base NBASE^2, and
                               9367                 :                :      * construct the base-NBASE result digits.  Note that this is still done
                               9368                 :                :      * at full precision w/guard digits.
                               9369                 :                :      */
                               9370                 :           2721 :     alloc_var(result, res_ndigits);
 8205 tgl@sss.pgh.pa.us        9371                 :           2721 :     res_digits = result->digits;
                               9372                 :           2721 :     carry = 0;
  337 dean.a.rasheed@gmail     9373         [ +  + ]:          24771 :     for (i = res_ndigitpairs - 1; i >= 0; i--)
                               9374                 :                :     {
                               9375                 :          22050 :         newdig = dividend[i] + carry;
 8205 tgl@sss.pgh.pa.us        9376         [ +  + ]:          22050 :         if (newdig < 0)
                               9377                 :                :         {
  337 dean.a.rasheed@gmail     9378                 :              3 :             carry = -((-newdig - 1) / NBASE_SQR) - 1;
                               9379                 :              3 :             newdig -= carry * NBASE_SQR;
                               9380                 :                :         }
                               9381         [ -  + ]:          22047 :         else if (newdig >= NBASE_SQR)
                               9382                 :                :         {
  337 dean.a.rasheed@gmail     9383                 :UBC           0 :             carry = newdig / NBASE_SQR;
                               9384                 :              0 :             newdig -= carry * NBASE_SQR;
                               9385                 :                :         }
                               9386                 :                :         else
 8205 tgl@sss.pgh.pa.us        9387                 :CBC       22047 :             carry = 0;
  337 dean.a.rasheed@gmail     9388                 :          22050 :         res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
                               9389                 :          22050 :         res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
                               9390                 :                :     }
 8205 tgl@sss.pgh.pa.us        9391         [ -  + ]:           2721 :     Assert(carry == 0);
                               9392                 :                : 
  337 dean.a.rasheed@gmail     9393                 :           2721 :     pfree(dividend);
                               9394                 :                : 
                               9395                 :                :     /*
                               9396                 :                :      * Finally, round or truncate the result to the requested precision.
                               9397                 :                :      */
 8205 tgl@sss.pgh.pa.us        9398                 :           2721 :     result->weight = res_weight;
                               9399                 :           2721 :     result->sign = res_sign;
                               9400                 :                : 
                               9401                 :                :     /* Round or truncate to target rscale (and set result->dscale) */
 7399 bruce@momjian.us         9402         [ +  + ]:           2721 :     if (round)
                               9403                 :            453 :         round_var(result, rscale);
                               9404                 :                :     else
                               9405                 :           2268 :         trunc_var(result, rscale);
                               9406                 :                : 
                               9407                 :                :     /* Strip leading and trailing zeroes */
 8205 tgl@sss.pgh.pa.us        9408                 :           2721 :     strip_var(result);
                               9409                 :                : }
                               9410                 :                : 
                               9411                 :                : 
                               9412                 :                : /*
                               9413                 :                :  * div_var_int() -
                               9414                 :                :  *
                               9415                 :                :  *  Divide a numeric variable by a 32-bit integer with the specified weight.
                               9416                 :                :  *  The quotient var / (ival * NBASE^ival_weight) is stored in result.
                               9417                 :                :  */
                               9418                 :                : static void
 1287 dean.a.rasheed@gmail     9419                 :         292105 : div_var_int(const NumericVar *var, int ival, int ival_weight,
                               9420                 :                :             NumericVar *result, int rscale, bool round)
                               9421                 :                : {
                               9422                 :         292105 :     NumericDigit *var_digits = var->digits;
                               9423                 :         292105 :     int         var_ndigits = var->ndigits;
                               9424                 :                :     int         res_sign;
                               9425                 :                :     int         res_weight;
                               9426                 :                :     int         res_ndigits;
                               9427                 :                :     NumericDigit *res_buf;
                               9428                 :                :     NumericDigit *res_digits;
                               9429                 :                :     uint32      divisor;
                               9430                 :                :     int         i;
                               9431                 :                : 
                               9432                 :                :     /* Guard against division by zero */
                               9433         [ -  + ]:         292105 :     if (ival == 0)
 1287 dean.a.rasheed@gmail     9434         [ #  # ]:UBC           0 :         ereport(ERROR,
                               9435                 :                :                 errcode(ERRCODE_DIVISION_BY_ZERO),
                               9436                 :                :                 errmsg("division by zero"));
                               9437                 :                : 
                               9438                 :                :     /* Result zero check */
 1287 dean.a.rasheed@gmail     9439         [ +  + ]:CBC      292105 :     if (var_ndigits == 0)
                               9440                 :                :     {
                               9441                 :           1151 :         zero_var(result);
                               9442                 :           1151 :         result->dscale = rscale;
                               9443                 :           1151 :         return;
                               9444                 :                :     }
                               9445                 :                : 
                               9446                 :                :     /*
                               9447                 :                :      * Determine the result sign, weight and number of digits to calculate.
                               9448                 :                :      * The weight figured here is correct if the emitted quotient has no
                               9449                 :                :      * leading zero digits; otherwise strip_var() will fix things up.
                               9450                 :                :      */
                               9451         [ +  + ]:         290954 :     if (var->sign == NUMERIC_POS)
                               9452         [ +  + ]:         289460 :         res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
                               9453                 :                :     else
                               9454         [ +  + ]:           1494 :         res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
                               9455                 :         290954 :     res_weight = var->weight - ival_weight;
                               9456                 :                :     /* The number of accurate result digits we need to produce: */
                               9457                 :         290954 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               9458                 :                :     /* ... but always at least 1 */
                               9459                 :         290954 :     res_ndigits = Max(res_ndigits, 1);
                               9460                 :                :     /* If rounding needed, figure one more digit to ensure correct result */
                               9461         [ +  + ]:         290954 :     if (round)
                               9462                 :          83342 :         res_ndigits++;
                               9463                 :                : 
                               9464                 :         290954 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                               9465                 :         290954 :     res_buf[0] = 0;             /* spare digit for later rounding */
                               9466                 :         290954 :     res_digits = res_buf + 1;
                               9467                 :                : 
                               9468                 :                :     /*
                               9469                 :                :      * Now compute the quotient digits.  This is the short division algorithm
                               9470                 :                :      * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
                               9471                 :                :      * allow the divisor to exceed the internal base.
                               9472                 :                :      *
                               9473                 :                :      * In this algorithm, the carry from one digit to the next is at most
                               9474                 :                :      * divisor - 1.  Therefore, while processing the next digit, carry may
                               9475                 :                :      * become as large as divisor * NBASE - 1, and so it requires a 64-bit
                               9476                 :                :      * integer if this exceeds UINT_MAX.
                               9477                 :                :      */
 1065 peter@eisentraut.org     9478                 :         290954 :     divisor = abs(ival);
                               9479                 :                : 
 1287 dean.a.rasheed@gmail     9480         [ +  + ]:         290954 :     if (divisor <= UINT_MAX / NBASE)
                               9481                 :                :     {
                               9482                 :                :         /* carry cannot overflow 32 bits */
                               9483                 :         289337 :         uint32      carry = 0;
                               9484                 :                : 
                               9485         [ +  + ]:        1422451 :         for (i = 0; i < res_ndigits; i++)
                               9486                 :                :         {
                               9487         [ +  + ]:        1133114 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9488                 :        1133114 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9489                 :        1133114 :             carry = carry % divisor;
                               9490                 :                :         }
                               9491                 :                :     }
                               9492                 :                :     else
                               9493                 :                :     {
                               9494                 :                :         /* carry may exceed 32 bits */
                               9495                 :           1617 :         uint64      carry = 0;
                               9496                 :                : 
                               9497         [ +  + ]:           5184 :         for (i = 0; i < res_ndigits; i++)
                               9498                 :                :         {
                               9499         [ +  + ]:           3567 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9500                 :           3567 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9501                 :           3567 :             carry = carry % divisor;
                               9502                 :                :         }
                               9503                 :                :     }
                               9504                 :                : 
                               9505                 :                :     /* Store the quotient in result */
                               9506         [ +  + ]:         290954 :     digitbuf_free(result->buf);
                               9507                 :         290954 :     result->ndigits = res_ndigits;
                               9508                 :         290954 :     result->buf = res_buf;
                               9509                 :         290954 :     result->digits = res_digits;
                               9510                 :         290954 :     result->weight = res_weight;
                               9511                 :         290954 :     result->sign = res_sign;
                               9512                 :                : 
                               9513                 :                :     /* Round or truncate to target rscale (and set result->dscale) */
                               9514         [ +  + ]:         290954 :     if (round)
                               9515                 :          83342 :         round_var(result, rscale);
                               9516                 :                :     else
                               9517                 :         207612 :         trunc_var(result, rscale);
                               9518                 :                : 
                               9519                 :                :     /* Strip leading/trailing zeroes */
                               9520                 :         290954 :     strip_var(result);
                               9521                 :                : }
                               9522                 :                : 
                               9523                 :                : 
                               9524                 :                : #ifdef HAVE_INT128
                               9525                 :                : /*
                               9526                 :                :  * div_var_int64() -
                               9527                 :                :  *
                               9528                 :                :  *  Divide a numeric variable by a 64-bit integer with the specified weight.
                               9529                 :                :  *  The quotient var / (ival * NBASE^ival_weight) is stored in result.
                               9530                 :                :  *
                               9531                 :                :  *  This duplicates the logic in div_var_int(), so any changes made there
                               9532                 :                :  *  should be made here too.
                               9533                 :                :  */
                               9534                 :                : static void
  957                          9535                 :            264 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
                               9536                 :                :               NumericVar *result, int rscale, bool round)
                               9537                 :                : {
                               9538                 :            264 :     NumericDigit *var_digits = var->digits;
                               9539                 :            264 :     int         var_ndigits = var->ndigits;
                               9540                 :                :     int         res_sign;
                               9541                 :                :     int         res_weight;
                               9542                 :                :     int         res_ndigits;
                               9543                 :                :     NumericDigit *res_buf;
                               9544                 :                :     NumericDigit *res_digits;
                               9545                 :                :     uint64      divisor;
                               9546                 :                :     int         i;
                               9547                 :                : 
                               9548                 :                :     /* Guard against division by zero */
                               9549         [ -  + ]:            264 :     if (ival == 0)
  957 dean.a.rasheed@gmail     9550         [ #  # ]:UBC           0 :         ereport(ERROR,
                               9551                 :                :                 errcode(ERRCODE_DIVISION_BY_ZERO),
                               9552                 :                :                 errmsg("division by zero"));
                               9553                 :                : 
                               9554                 :                :     /* Result zero check */
  957 dean.a.rasheed@gmail     9555         [ +  + ]:CBC         264 :     if (var_ndigits == 0)
                               9556                 :                :     {
                               9557                 :             48 :         zero_var(result);
                               9558                 :             48 :         result->dscale = rscale;
                               9559                 :             48 :         return;
                               9560                 :                :     }
                               9561                 :                : 
                               9562                 :                :     /*
                               9563                 :                :      * Determine the result sign, weight and number of digits to calculate.
                               9564                 :                :      * The weight figured here is correct if the emitted quotient has no
                               9565                 :                :      * leading zero digits; otherwise strip_var() will fix things up.
                               9566                 :                :      */
                               9567         [ +  + ]:            216 :     if (var->sign == NUMERIC_POS)
                               9568         [ +  + ]:            129 :         res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
                               9569                 :                :     else
                               9570         [ +  + ]:             87 :         res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
                               9571                 :            216 :     res_weight = var->weight - ival_weight;
                               9572                 :                :     /* The number of accurate result digits we need to produce: */
                               9573                 :            216 :     res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                               9574                 :                :     /* ... but always at least 1 */
                               9575                 :            216 :     res_ndigits = Max(res_ndigits, 1);
                               9576                 :                :     /* If rounding needed, figure one more digit to ensure correct result */
                               9577         [ +  + ]:            216 :     if (round)
                               9578                 :            213 :         res_ndigits++;
                               9579                 :                : 
                               9580                 :            216 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                               9581                 :            216 :     res_buf[0] = 0;             /* spare digit for later rounding */
                               9582                 :            216 :     res_digits = res_buf + 1;
                               9583                 :                : 
                               9584                 :                :     /*
                               9585                 :                :      * Now compute the quotient digits.  This is the short division algorithm
                               9586                 :                :      * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
                               9587                 :                :      * allow the divisor to exceed the internal base.
                               9588                 :                :      *
                               9589                 :                :      * In this algorithm, the carry from one digit to the next is at most
                               9590                 :                :      * divisor - 1.  Therefore, while processing the next digit, carry may
                               9591                 :                :      * become as large as divisor * NBASE - 1, and so it requires a 128-bit
                               9592                 :                :      * integer if this exceeds PG_UINT64_MAX.
                               9593                 :                :      */
                               9594                 :            216 :     divisor = i64abs(ival);
                               9595                 :                : 
                               9596         [ +  + ]:            216 :     if (divisor <= PG_UINT64_MAX / NBASE)
                               9597                 :                :     {
                               9598                 :                :         /* carry cannot overflow 64 bits */
                               9599                 :            168 :         uint64      carry = 0;
                               9600                 :                : 
                               9601         [ +  + ]:           1707 :         for (i = 0; i < res_ndigits; i++)
                               9602                 :                :         {
                               9603         [ +  + ]:           1539 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9604                 :           1539 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9605                 :           1539 :             carry = carry % divisor;
                               9606                 :                :         }
                               9607                 :                :     }
                               9608                 :                :     else
                               9609                 :                :     {
                               9610                 :                :         /* carry may exceed 64 bits */
                               9611                 :             48 :         uint128     carry = 0;
                               9612                 :                : 
                               9613         [ +  + ]:            516 :         for (i = 0; i < res_ndigits; i++)
                               9614                 :                :         {
                               9615         [ +  + ]:            468 :             carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
                               9616                 :            468 :             res_digits[i] = (NumericDigit) (carry / divisor);
                               9617                 :            468 :             carry = carry % divisor;
                               9618                 :                :         }
                               9619                 :                :     }
                               9620                 :                : 
                               9621                 :                :     /* Store the quotient in result */
                               9622         [ +  + ]:            216 :     digitbuf_free(result->buf);
                               9623                 :            216 :     result->ndigits = res_ndigits;
                               9624                 :            216 :     result->buf = res_buf;
                               9625                 :            216 :     result->digits = res_digits;
                               9626                 :            216 :     result->weight = res_weight;
                               9627                 :            216 :     result->sign = res_sign;
                               9628                 :                : 
                               9629                 :                :     /* Round or truncate to target rscale (and set result->dscale) */
                               9630         [ +  + ]:            216 :     if (round)
                               9631                 :            213 :         round_var(result, rscale);
                               9632                 :                :     else
                               9633                 :              3 :         trunc_var(result, rscale);
                               9634                 :                : 
                               9635                 :                :     /* Strip leading/trailing zeroes */
                               9636                 :            216 :     strip_var(result);
                               9637                 :                : }
                               9638                 :                : #endif
                               9639                 :                : 
                               9640                 :                : 
                               9641                 :                : /*
                               9642                 :                :  * Default scale selection for division
                               9643                 :                :  *
                               9644                 :                :  * Returns the appropriate result scale for the division result.
                               9645                 :                :  */
                               9646                 :                : static int
 2918 andres@anarazel.de       9647                 :          74810 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
                               9648                 :                : {
                               9649                 :                :     int         weight1,
                               9650                 :                :                 weight2,
                               9651                 :                :                 qweight,
                               9652                 :                :                 i;
                               9653                 :                :     NumericDigit firstdigit1,
                               9654                 :                :                 firstdigit2;
                               9655                 :                :     int         rscale;
                               9656                 :                : 
                               9657                 :                :     /*
                               9658                 :                :      * The result scale of a division isn't specified in any SQL standard. For
                               9659                 :                :      * PostgreSQL we select a result scale that will give at least
                               9660                 :                :      * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
                               9661                 :                :      * result no less accurate than float8; but use a scale not less than
                               9662                 :                :      * either input's display scale.
                               9663                 :                :      */
                               9664                 :                : 
                               9665                 :                :     /* Get the actual (normalized) weight and first digit of each input */
                               9666                 :                : 
 8375 tgl@sss.pgh.pa.us        9667                 :          74810 :     weight1 = 0;                /* values to use if var1 is zero */
                               9668                 :          74810 :     firstdigit1 = 0;
                               9669         [ +  + ]:          74810 :     for (i = 0; i < var1->ndigits; i++)
                               9670                 :                :     {
                               9671                 :          73959 :         firstdigit1 = var1->digits[i];
                               9672         [ +  - ]:          73959 :         if (firstdigit1 != 0)
                               9673                 :                :         {
                               9674                 :          73959 :             weight1 = var1->weight - i;
                               9675                 :          73959 :             break;
                               9676                 :                :         }
                               9677                 :                :     }
                               9678                 :                : 
                               9679                 :          74810 :     weight2 = 0;                /* values to use if var2 is zero */
                               9680                 :          74810 :     firstdigit2 = 0;
                               9681         [ +  + ]:          74810 :     for (i = 0; i < var2->ndigits; i++)
                               9682                 :                :     {
                               9683                 :          74785 :         firstdigit2 = var2->digits[i];
                               9684         [ +  - ]:          74785 :         if (firstdigit2 != 0)
                               9685                 :                :         {
                               9686                 :          74785 :             weight2 = var2->weight - i;
                               9687                 :          74785 :             break;
                               9688                 :                :         }
                               9689                 :                :     }
                               9690                 :                : 
                               9691                 :                :     /*
                               9692                 :                :      * Estimate weight of quotient.  If the two first digits are equal, we
                               9693                 :                :      * can't be sure, but assume that var1 is less than var2.
                               9694                 :                :      */
                               9695                 :          74810 :     qweight = weight1 - weight2;
                               9696         [ +  + ]:          74810 :     if (firstdigit1 <= firstdigit2)
                               9697                 :          66400 :         qweight--;
                               9698                 :                : 
                               9699                 :                :     /* Select result scale */
 8205                          9700                 :          74810 :     rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
                               9701                 :          74810 :     rscale = Max(rscale, var1->dscale);
                               9702                 :          74810 :     rscale = Max(rscale, var2->dscale);
                               9703                 :          74810 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                               9704                 :          74810 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                               9705                 :                : 
                               9706                 :          74810 :     return rscale;
                               9707                 :                : }
                               9708                 :                : 
                               9709                 :                : 
                               9710                 :                : /*
                               9711                 :                :  * mod_var() -
                               9712                 :                :  *
                               9713                 :                :  *  Calculate the modulo of two numerics at variable level
                               9714                 :                :  */
                               9715                 :                : static void
 2918 andres@anarazel.de       9716                 :         206844 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               9717                 :                : {
                               9718                 :                :     NumericVar  tmp;
                               9719                 :                : 
 9747 JanWieck@Yahoo.com       9720                 :         206844 :     init_var(&tmp);
                               9721                 :                : 
                               9722                 :                :     /* ---------
                               9723                 :                :      * We do this using the equation
                               9724                 :                :      *      mod(x,y) = x - trunc(x/y)*y
                               9725                 :                :      * div_var can be persuaded to give us trunc(x/y) directly.
                               9726                 :                :      * ----------
                               9727                 :                :      */
  337 dean.a.rasheed@gmail     9728                 :         206844 :     div_var(var1, var2, &tmp, 0, false, true);
                               9729                 :                : 
 6364 tgl@sss.pgh.pa.us        9730                 :         206844 :     mul_var(var2, &tmp, &tmp, var2->dscale);
                               9731                 :                : 
 9747 JanWieck@Yahoo.com       9732                 :         206844 :     sub_var(var1, &tmp, result);
                               9733                 :                : 
                               9734                 :         206844 :     free_var(&tmp);
                               9735                 :         206844 : }
                               9736                 :                : 
                               9737                 :                : 
                               9738                 :                : /*
                               9739                 :                :  * div_mod_var() -
                               9740                 :                :  *
                               9741                 :                :  *  Calculate the truncated integer quotient and numeric remainder of two
                               9742                 :                :  *  numeric variables.  The remainder is precise to var2's dscale.
                               9743                 :                :  */
                               9744                 :                : static void
 1988 dean.a.rasheed@gmail     9745                 :           2259 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
                               9746                 :                :             NumericVar *quot, NumericVar *rem)
                               9747                 :                : {
                               9748                 :                :     NumericVar  q;
                               9749                 :                :     NumericVar  r;
                               9750                 :                : 
                               9751                 :           2259 :     init_var(&q);
                               9752                 :           2259 :     init_var(&r);
                               9753                 :                : 
                               9754                 :                :     /*
                               9755                 :                :      * Use div_var() with exact = false to get an initial estimate for the
                               9756                 :                :      * integer quotient (truncated towards zero).  This might be slightly
                               9757                 :                :      * inaccurate, but we correct it below.
                               9758                 :                :      */
  337                          9759                 :           2259 :     div_var(var1, var2, &q, 0, false, false);
                               9760                 :                : 
                               9761                 :                :     /* Compute initial estimate of remainder using the quotient estimate. */
 1988                          9762                 :           2259 :     mul_var(var2, &q, &r, var2->dscale);
                               9763                 :           2259 :     sub_var(var1, &r, &r);
                               9764                 :                : 
                               9765                 :                :     /*
                               9766                 :                :      * Adjust the results if necessary --- the remainder should have the same
                               9767                 :                :      * sign as var1, and its absolute value should be less than the absolute
                               9768                 :                :      * value of var2.
                               9769                 :                :      */
                               9770   [ +  -  -  + ]:           2259 :     while (r.ndigits != 0 && r.sign != var1->sign)
                               9771                 :                :     {
                               9772                 :                :         /* The absolute value of the quotient is too large */
 1988 dean.a.rasheed@gmail     9773         [ #  # ]:UBC           0 :         if (var1->sign == var2->sign)
                               9774                 :                :         {
                               9775                 :              0 :             sub_var(&q, &const_one, &q);
                               9776                 :              0 :             add_var(&r, var2, &r);
                               9777                 :                :         }
                               9778                 :                :         else
                               9779                 :                :         {
                               9780                 :              0 :             add_var(&q, &const_one, &q);
                               9781                 :              0 :             sub_var(&r, var2, &r);
                               9782                 :                :         }
                               9783                 :                :     }
                               9784                 :                : 
 1988 dean.a.rasheed@gmail     9785         [ -  + ]:CBC        2259 :     while (cmp_abs(&r, var2) >= 0)
                               9786                 :                :     {
                               9787                 :                :         /* The absolute value of the quotient is too small */
 1988 dean.a.rasheed@gmail     9788         [ #  # ]:UBC           0 :         if (var1->sign == var2->sign)
                               9789                 :                :         {
                               9790                 :              0 :             add_var(&q, &const_one, &q);
                               9791                 :              0 :             sub_var(&r, var2, &r);
                               9792                 :                :         }
                               9793                 :                :         else
                               9794                 :                :         {
                               9795                 :              0 :             sub_var(&q, &const_one, &q);
                               9796                 :              0 :             add_var(&r, var2, &r);
                               9797                 :                :         }
                               9798                 :                :     }
                               9799                 :                : 
 1988 dean.a.rasheed@gmail     9800                 :CBC        2259 :     set_var_from_var(&q, quot);
                               9801                 :           2259 :     set_var_from_var(&r, rem);
                               9802                 :                : 
                               9803                 :           2259 :     free_var(&q);
                               9804                 :           2259 :     free_var(&r);
                               9805                 :           2259 : }
                               9806                 :                : 
                               9807                 :                : 
                               9808                 :                : /*
                               9809                 :                :  * ceil_var() -
                               9810                 :                :  *
                               9811                 :                :  *  Return the smallest integer greater than or equal to the argument
                               9812                 :                :  *  on variable level
                               9813                 :                :  */
                               9814                 :                : static void
 2918 andres@anarazel.de       9815                 :            102 : ceil_var(const NumericVar *var, NumericVar *result)
                               9816                 :                : {
                               9817                 :                :     NumericVar  tmp;
                               9818                 :                : 
 9747 JanWieck@Yahoo.com       9819                 :            102 :     init_var(&tmp);
                               9820                 :            102 :     set_var_from_var(var, &tmp);
                               9821                 :                : 
 8205 tgl@sss.pgh.pa.us        9822                 :            102 :     trunc_var(&tmp, 0);
                               9823                 :                : 
                               9824   [ +  +  +  + ]:            102 :     if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
 9747 JanWieck@Yahoo.com       9825                 :             30 :         add_var(&tmp, &const_one, &tmp);
                               9826                 :                : 
                               9827                 :            102 :     set_var_from_var(&tmp, result);
                               9828                 :            102 :     free_var(&tmp);
                               9829                 :            102 : }
                               9830                 :                : 
                               9831                 :                : 
                               9832                 :                : /*
                               9833                 :                :  * floor_var() -
                               9834                 :                :  *
                               9835                 :                :  *  Return the largest integer equal to or less than the argument
                               9836                 :                :  *  on variable level
                               9837                 :                :  */
                               9838                 :                : static void
 2918 andres@anarazel.de       9839                 :             54 : floor_var(const NumericVar *var, NumericVar *result)
                               9840                 :                : {
                               9841                 :                :     NumericVar  tmp;
                               9842                 :                : 
 9747 JanWieck@Yahoo.com       9843                 :             54 :     init_var(&tmp);
                               9844                 :             54 :     set_var_from_var(var, &tmp);
                               9845                 :                : 
 8205 tgl@sss.pgh.pa.us        9846                 :             54 :     trunc_var(&tmp, 0);
                               9847                 :                : 
                               9848   [ +  +  +  + ]:             54 :     if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
 9747 JanWieck@Yahoo.com       9849                 :             15 :         sub_var(&tmp, &const_one, &tmp);
                               9850                 :                : 
                               9851                 :             54 :     set_var_from_var(&tmp, result);
                               9852                 :             54 :     free_var(&tmp);
                               9853                 :             54 : }
                               9854                 :                : 
                               9855                 :                : 
                               9856                 :                : /*
                               9857                 :                :  * gcd_var() -
                               9858                 :                :  *
                               9859                 :                :  *  Calculate the greatest common divisor of two numerics at variable level
                               9860                 :                :  */
                               9861                 :                : static void
 2051 dean.a.rasheed@gmail     9862                 :            111 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                               9863                 :                : {
                               9864                 :                :     int         res_dscale;
                               9865                 :                :     int         cmp;
                               9866                 :                :     NumericVar  tmp_arg;
                               9867                 :                :     NumericVar  mod;
                               9868                 :                : 
                               9869                 :            111 :     res_dscale = Max(var1->dscale, var2->dscale);
                               9870                 :                : 
                               9871                 :                :     /*
                               9872                 :                :      * Arrange for var1 to be the number with the greater absolute value.
                               9873                 :                :      *
                               9874                 :                :      * This would happen automatically in the loop below, but avoids an
                               9875                 :                :      * expensive modulo operation.
                               9876                 :                :      */
                               9877                 :            111 :     cmp = cmp_abs(var1, var2);
                               9878         [ +  + ]:            111 :     if (cmp < 0)
                               9879                 :                :     {
                               9880                 :             42 :         const NumericVar *tmp = var1;
                               9881                 :                : 
                               9882                 :             42 :         var1 = var2;
                               9883                 :             42 :         var2 = tmp;
                               9884                 :                :     }
                               9885                 :                : 
                               9886                 :                :     /*
                               9887                 :                :      * Also avoid the taking the modulo if the inputs have the same absolute
                               9888                 :                :      * value, or if the smaller input is zero.
                               9889                 :                :      */
                               9890   [ +  +  +  + ]:            111 :     if (cmp == 0 || var2->ndigits == 0)
                               9891                 :                :     {
                               9892                 :             36 :         set_var_from_var(var1, result);
                               9893                 :             36 :         result->sign = NUMERIC_POS;
                               9894                 :             36 :         result->dscale = res_dscale;
                               9895                 :             36 :         return;
                               9896                 :                :     }
                               9897                 :                : 
                               9898                 :             75 :     init_var(&tmp_arg);
                               9899                 :             75 :     init_var(&mod);
                               9900                 :                : 
                               9901                 :                :     /* Use the Euclidean algorithm to find the GCD */
                               9902                 :             75 :     set_var_from_var(var1, &tmp_arg);
                               9903                 :             75 :     set_var_from_var(var2, result);
                               9904                 :                : 
                               9905                 :                :     for (;;)
                               9906                 :                :     {
                               9907                 :                :         /* this loop can take a while, so allow it to be interrupted */
                               9908         [ -  + ]:            294 :         CHECK_FOR_INTERRUPTS();
                               9909                 :                : 
                               9910                 :            294 :         mod_var(&tmp_arg, result, &mod);
                               9911         [ +  + ]:            294 :         if (mod.ndigits == 0)
                               9912                 :             75 :             break;
                               9913                 :            219 :         set_var_from_var(result, &tmp_arg);
                               9914                 :            219 :         set_var_from_var(&mod, result);
                               9915                 :                :     }
                               9916                 :             75 :     result->sign = NUMERIC_POS;
                               9917                 :             75 :     result->dscale = res_dscale;
                               9918                 :                : 
                               9919                 :             75 :     free_var(&tmp_arg);
                               9920                 :             75 :     free_var(&mod);
                               9921                 :                : }
                               9922                 :                : 
                               9923                 :                : 
                               9924                 :                : /*
                               9925                 :                :  * sqrt_var() -
                               9926                 :                :  *
                               9927                 :                :  *  Compute the square root of x using the Karatsuba Square Root algorithm.
                               9928                 :                :  *  NOTE: we allow rscale < 0 here, implying rounding before the decimal
                               9929                 :                :  *  point.
                               9930                 :                :  */
                               9931                 :                : static void
 2918 andres@anarazel.de       9932                 :           2097 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
                               9933                 :                : {
                               9934                 :                :     int         stat;
                               9935                 :                :     int         res_weight;
                               9936                 :                :     int         res_ndigits;
                               9937                 :                :     int         src_ndigits;
                               9938                 :                :     int         step;
                               9939                 :                :     int         ndigits[32];
                               9940                 :                :     int         blen;
                               9941                 :                :     int64       arg_int64;
                               9942                 :                :     int         src_idx;
                               9943                 :                :     int64       s_int64;
                               9944                 :                :     int64       r_int64;
                               9945                 :                :     NumericVar  s_var;
                               9946                 :                :     NumericVar  r_var;
                               9947                 :                :     NumericVar  a0_var;
                               9948                 :                :     NumericVar  a1_var;
                               9949                 :                :     NumericVar  q_var;
                               9950                 :                :     NumericVar  u_var;
                               9951                 :                : 
 9747 JanWieck@Yahoo.com       9952                 :           2097 :     stat = cmp_var(arg, &const_zero);
                               9953         [ +  + ]:           2097 :     if (stat == 0)
                               9954                 :                :     {
 8205 tgl@sss.pgh.pa.us        9955                 :              9 :         zero_var(result);
                               9956                 :              9 :         result->dscale = rscale;
 9747 JanWieck@Yahoo.com       9957                 :              9 :         return;
                               9958                 :                :     }
                               9959                 :                : 
                               9960                 :                :     /*
                               9961                 :                :      * SQL2003 defines sqrt() in terms of power, so we need to emit the right
                               9962                 :                :      * SQLSTATE error code if the operand is negative.
                               9963                 :                :      */
                               9964         [ +  + ]:           2088 :     if (stat < 0)
 8077 tgl@sss.pgh.pa.us        9965         [ +  - ]:              3 :         ereport(ERROR,
                               9966                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                               9967                 :                :                  errmsg("cannot take square root of a negative number")));
                               9968                 :                : 
 1988 dean.a.rasheed@gmail     9969                 :           2085 :     init_var(&s_var);
                               9970                 :           2085 :     init_var(&r_var);
                               9971                 :           2085 :     init_var(&a0_var);
                               9972                 :           2085 :     init_var(&a1_var);
                               9973                 :           2085 :     init_var(&q_var);
                               9974                 :           2085 :     init_var(&u_var);
                               9975                 :                : 
                               9976                 :                :     /*
                               9977                 :                :      * The result weight is half the input weight, rounded towards minus
                               9978                 :                :      * infinity --- res_weight = floor(arg->weight / 2).
                               9979                 :                :      */
                               9980         [ +  + ]:           2085 :     if (arg->weight >= 0)
                               9981                 :           1929 :         res_weight = arg->weight / 2;
                               9982                 :                :     else
                               9983                 :            156 :         res_weight = -((-arg->weight - 1) / 2 + 1);
                               9984                 :                : 
                               9985                 :                :     /*
                               9986                 :                :      * Number of NBASE digits to compute.  To ensure correct rounding, compute
                               9987                 :                :      * at least 1 extra decimal digit.  We explicitly allow rscale to be
                               9988                 :                :      * negative here, but must always compute at least 1 NBASE digit.  Thus
                               9989                 :                :      * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
                               9990                 :                :      */
                               9991         [ +  - ]:           2085 :     if (rscale + 1 >= 0)
                               9992                 :           2085 :         res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
                               9993                 :                :     else
 1988 dean.a.rasheed@gmail     9994                 :UBC           0 :         res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
 1988 dean.a.rasheed@gmail     9995                 :CBC        2085 :     res_ndigits = Max(res_ndigits, 1);
                               9996                 :                : 
                               9997                 :                :     /*
                               9998                 :                :      * Number of source NBASE digits logically required to produce a result
                               9999                 :                :      * with this precision --- every digit before the decimal point, plus 2
                              10000                 :                :      * for each result digit after the decimal point (or minus 2 for each
                              10001                 :                :      * result digit we round before the decimal point).
                              10002                 :                :      */
                              10003                 :           2085 :     src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
                              10004                 :           2085 :     src_ndigits = Max(src_ndigits, 1);
                              10005                 :                : 
                              10006                 :                :     /* ----------
                              10007                 :                :      * From this point on, we treat the input and the result as integers and
                              10008                 :                :      * compute the integer square root and remainder using the Karatsuba
                              10009                 :                :      * Square Root algorithm, which may be written recursively as follows:
                              10010                 :                :      *
                              10011                 :                :      *  SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
                              10012                 :                :      *      [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
                              10013                 :                :      *        0 <= a0,a1,a2 < b and a3 >= b/4 ]
                              10014                 :                :      *      Let (s,r) = SqrtRem(a3*b + a2)
                              10015                 :                :      *      Let (q,u) = DivRem(r*b + a1, 2*s)
                              10016                 :                :      *      Let s = s*b + q
                              10017                 :                :      *      Let r = u*b + a0 - q^2
                              10018                 :                :      *      If r < 0 Then
                              10019                 :                :      *          Let r = r + s
                              10020                 :                :      *          Let s = s - 1
                              10021                 :                :      *          Let r = r + s
                              10022                 :                :      *      Return (s,r)
                              10023                 :                :      *
                              10024                 :                :      * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
                              10025                 :                :      * RR-3805, November 1999.  At the time of writing this was available
                              10026                 :                :      * on the net at <https://hal.inria.fr/inria-00072854>.
                              10027                 :                :      *
                              10028                 :                :      * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
                              10029                 :                :      * "choose a base b such that n requires at least four base-b digits to
                              10030                 :                :      * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
                              10031                 :                :      * than b".  For optimal performance, b should have approximately a
                              10032                 :                :      * quarter the number of digits in the input, so that the outer square
                              10033                 :                :      * root computes roughly twice as many digits as the inner one.  For
                              10034                 :                :      * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
                              10035                 :                :      *
                              10036                 :                :      * We implement the algorithm iteratively rather than recursively, to
                              10037                 :                :      * allow the working variables to be reused.  With this approach, each
                              10038                 :                :      * digit of the input is read precisely once --- src_idx tracks the number
                              10039                 :                :      * of input digits used so far.
                              10040                 :                :      *
                              10041                 :                :      * The array ndigits[] holds the number of NBASE digits of the input that
                              10042                 :                :      * will have been used at the end of each iteration, which roughly doubles
                              10043                 :                :      * each time.  Note that the array elements are stored in reverse order,
                              10044                 :                :      * so if the final iteration requires src_ndigits = 37 input digits, the
                              10045                 :                :      * array will contain [37,19,11,7,5,3], and we would start by computing
                              10046                 :                :      * the square root of the 3 most significant NBASE digits.
                              10047                 :                :      *
                              10048                 :                :      * In each iteration, we choose blen to be the largest integer for which
                              10049                 :                :      * the input number has a3 >= b/4, when written in the form above.  In
                              10050                 :                :      * general, this means blen = src_ndigits / 4 (truncated), but if
                              10051                 :                :      * src_ndigits is a multiple of 4, that might lead to the coefficient a3
                              10052                 :                :      * being less than b/4 (if the first input digit is less than NBASE/4), in
                              10053                 :                :      * which case we choose blen = src_ndigits / 4 - 1.  The number of digits
                              10054                 :                :      * in the inner square root is then src_ndigits - 2*blen.  So, for
                              10055                 :                :      * example, if we have src_ndigits = 26 initially, the array ndigits[]
                              10056                 :                :      * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
                              10057                 :                :      * the first input digit.
                              10058                 :                :      *
                              10059                 :                :      * Additionally, we can put an upper bound on the number of steps required
                              10060                 :                :      * as follows --- suppose that the number of source digits is an n-bit
                              10061                 :                :      * number in the range [2^(n-1), 2^n-1], then blen will be in the range
                              10062                 :                :      * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
                              10063                 :                :      * root will be in the range [2^(n-2), 2^(n-1)+1].  In the next step, blen
                              10064                 :                :      * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
                              10065                 :                :      * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
                              10066                 :                :      * This pattern repeats, and in the worst case the array ndigits[] will
                              10067                 :                :      * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
                              10068                 :                :      * will require n steps.  Therefore, since all digit array sizes are
                              10069                 :                :      * signed 32-bit integers, the number of steps required is guaranteed to
                              10070                 :                :      * be less than 32.
                              10071                 :                :      * ----------
                              10072                 :                :      */
                              10073                 :           2085 :     step = 0;
                              10074         [ +  + ]:           9981 :     while ((ndigits[step] = src_ndigits) > 4)
                              10075                 :                :     {
                              10076                 :                :         /* Choose b so that a3 >= b/4, as described above */
                              10077                 :           7896 :         blen = src_ndigits / 4;
                              10078   [ +  +  +  + ]:           7896 :         if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
                              10079                 :            162 :             blen--;
                              10080                 :                : 
                              10081                 :                :         /* Number of digits in the next step (inner square root) */
                              10082                 :           7896 :         src_ndigits -= 2 * blen;
                              10083                 :           7896 :         step++;
                              10084                 :                :     }
                              10085                 :                : 
                              10086                 :                :     /*
                              10087                 :                :      * First iteration (innermost square root and remainder):
                              10088                 :                :      *
                              10089                 :                :      * Here src_ndigits <= 4, and the input fits in an int64.  Its square root
                              10090                 :                :      * has at most 9 decimal digits, so estimate it using double precision
                              10091                 :                :      * arithmetic, which will in fact almost certainly return the correct
                              10092                 :                :      * result with no further correction required.
                              10093                 :                :      */
                              10094                 :           2085 :     arg_int64 = arg->digits[0];
                              10095         [ +  + ]:           6657 :     for (src_idx = 1; src_idx < src_ndigits; src_idx++)
                              10096                 :                :     {
                              10097                 :           4572 :         arg_int64 *= NBASE;
                              10098         [ +  + ]:           4572 :         if (src_idx < arg->ndigits)
                              10099                 :           3843 :             arg_int64 += arg->digits[src_idx];
                              10100                 :                :     }
                              10101                 :                : 
                              10102                 :           2085 :     s_int64 = (int64) sqrt((double) arg_int64);
                              10103                 :           2085 :     r_int64 = arg_int64 - s_int64 * s_int64;
                              10104                 :                : 
                              10105                 :                :     /*
                              10106                 :                :      * Use Newton's method to correct the result, if necessary.
                              10107                 :                :      *
                              10108                 :                :      * This uses integer division with truncation to compute the truncated
                              10109                 :                :      * integer square root by iterating using the formula x -> (x + n/x) / 2.
                              10110                 :                :      * This is known to converge to isqrt(n), unless n+1 is a perfect square.
                              10111                 :                :      * If n+1 is a perfect square, the sequence will oscillate between the two
                              10112                 :                :      * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
                              10113                 :                :      * checking the remainder.
                              10114                 :                :      */
                              10115   [ -  +  -  + ]:           2085 :     while (r_int64 < 0 || r_int64 > 2 * s_int64)
                              10116                 :                :     {
 1988 dean.a.rasheed@gmail    10117                 :UBC           0 :         s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
                              10118                 :              0 :         r_int64 = arg_int64 - s_int64 * s_int64;
                              10119                 :                :     }
                              10120                 :                : 
                              10121                 :                :     /*
                              10122                 :                :      * Iterations with src_ndigits <= 8:
                              10123                 :                :      *
                              10124                 :                :      * The next 1 or 2 iterations compute larger (outer) square roots with
                              10125                 :                :      * src_ndigits <= 8, so the result still fits in an int64 (even though the
                              10126                 :                :      * input no longer does) and we can continue to compute using int64
                              10127                 :                :      * variables to avoid more expensive numeric computations.
                              10128                 :                :      *
                              10129                 :                :      * It is fairly easy to see that there is no risk of the intermediate
                              10130                 :                :      * values below overflowing 64-bit integers.  In the worst case, the
                              10131                 :                :      * previous iteration will have computed a 3-digit square root (of a
                              10132                 :                :      * 6-digit input less than NBASE^6 / 4), so at the start of this
                              10133                 :                :      * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
                              10134                 :                :      * less than 10^12.  In this case, blen will be 1, so numer will be less
                              10135                 :                :      * than 10^17, and denom will be less than 10^12 (and hence u will also be
                              10136                 :                :      * less than 10^12).  Finally, since q^2 = u*b + a0 - r, we can also be
                              10137                 :                :      * sure that q^2 < 10^17.  Therefore all these quantities fit comfortably
                              10138                 :                :      * in 64-bit integers.
                              10139                 :                :      */
 1988 dean.a.rasheed@gmail    10140                 :CBC        2085 :     step--;
                              10141   [ +  -  +  + ]:           5283 :     while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
                              10142                 :                :     {
                              10143                 :                :         int         b;
                              10144                 :                :         int         a0;
                              10145                 :                :         int         a1;
                              10146                 :                :         int         i;
                              10147                 :                :         int64       numer;
                              10148                 :                :         int64       denom;
                              10149                 :                :         int64       q;
                              10150                 :                :         int64       u;
                              10151                 :                : 
                              10152                 :           3198 :         blen = (src_ndigits - src_idx) / 2;
                              10153                 :                : 
                              10154                 :                :         /* Extract a1 and a0, and compute b */
                              10155                 :           3198 :         a0 = 0;
                              10156                 :           3198 :         a1 = 0;
                              10157                 :           3198 :         b = 1;
                              10158                 :                : 
                              10159         [ +  + ]:           6468 :         for (i = 0; i < blen; i++, src_idx++)
                              10160                 :                :         {
                              10161                 :           3270 :             b *= NBASE;
                              10162                 :           3270 :             a1 *= NBASE;
                              10163         [ +  + ]:           3270 :             if (src_idx < arg->ndigits)
                              10164                 :           2400 :                 a1 += arg->digits[src_idx];
                              10165                 :                :         }
                              10166                 :                : 
                              10167         [ +  + ]:           6468 :         for (i = 0; i < blen; i++, src_idx++)
                              10168                 :                :         {
                              10169                 :           3270 :             a0 *= NBASE;
                              10170         [ +  + ]:           3270 :             if (src_idx < arg->ndigits)
                              10171                 :           2322 :                 a0 += arg->digits[src_idx];
                              10172                 :                :         }
                              10173                 :                : 
                              10174                 :                :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
                              10175                 :           3198 :         numer = r_int64 * b + a1;
                              10176                 :           3198 :         denom = 2 * s_int64;
                              10177                 :           3198 :         q = numer / denom;
                              10178                 :           3198 :         u = numer - q * denom;
                              10179                 :                : 
                              10180                 :                :         /* Compute s = s*b + q and r = u*b + a0 - q^2 */
                              10181                 :           3198 :         s_int64 = s_int64 * b + q;
                              10182                 :           3198 :         r_int64 = u * b + a0 - q * q;
                              10183                 :                : 
                              10184         [ +  + ]:           3198 :         if (r_int64 < 0)
                              10185                 :                :         {
                              10186                 :                :             /* s is too large by 1; set r += s, s--, r += s */
                              10187                 :            105 :             r_int64 += s_int64;
                              10188                 :            105 :             s_int64--;
                              10189                 :            105 :             r_int64 += s_int64;
                              10190                 :                :         }
                              10191                 :                : 
                              10192         [ -  + ]:           3198 :         Assert(src_idx == src_ndigits); /* All input digits consumed */
                              10193                 :           3198 :         step--;
                              10194                 :                :     }
                              10195                 :                : 
                              10196                 :                :     /*
                              10197                 :                :      * On platforms with 128-bit integer support, we can further delay the
                              10198                 :                :      * need to use numeric variables.
                              10199                 :                :      */
                              10200                 :                : #ifdef HAVE_INT128
                              10201         [ +  - ]:           2085 :     if (step >= 0)
                              10202                 :                :     {
                              10203                 :                :         int128      s_int128;
                              10204                 :                :         int128      r_int128;
                              10205                 :                : 
                              10206                 :           2085 :         s_int128 = s_int64;
                              10207                 :           2085 :         r_int128 = r_int64;
                              10208                 :                : 
                              10209                 :                :         /*
                              10210                 :                :          * Iterations with src_ndigits <= 16:
                              10211                 :                :          *
                              10212                 :                :          * The result fits in an int128 (even though the input doesn't) so we
                              10213                 :                :          * use int128 variables to avoid more expensive numeric computations.
                              10214                 :                :          */
                              10215   [ +  +  +  + ]:           4524 :         while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
                              10216                 :                :         {
                              10217                 :                :             int64       b;
                              10218                 :                :             int64       a0;
                              10219                 :                :             int64       a1;
                              10220                 :                :             int64       i;
                              10221                 :                :             int128      numer;
                              10222                 :                :             int128      denom;
                              10223                 :                :             int128      q;
                              10224                 :                :             int128      u;
                              10225                 :                : 
                              10226                 :           2439 :             blen = (src_ndigits - src_idx) / 2;
                              10227                 :                : 
                              10228                 :                :             /* Extract a1 and a0, and compute b */
                              10229                 :           2439 :             a0 = 0;
                              10230                 :           2439 :             a1 = 0;
                              10231                 :           2439 :             b = 1;
                              10232                 :                : 
                              10233         [ +  + ]:           8040 :             for (i = 0; i < blen; i++, src_idx++)
                              10234                 :                :             {
                              10235                 :           5601 :                 b *= NBASE;
                              10236                 :           5601 :                 a1 *= NBASE;
                              10237         [ +  + ]:           5601 :                 if (src_idx < arg->ndigits)
                              10238                 :           3303 :                     a1 += arg->digits[src_idx];
                              10239                 :                :             }
                              10240                 :                : 
                              10241         [ +  + ]:           8040 :             for (i = 0; i < blen; i++, src_idx++)
                              10242                 :                :             {
                              10243                 :           5601 :                 a0 *= NBASE;
                              10244         [ +  + ]:           5601 :                 if (src_idx < arg->ndigits)
                              10245                 :           2235 :                     a0 += arg->digits[src_idx];
                              10246                 :                :             }
                              10247                 :                : 
                              10248                 :                :             /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
                              10249                 :           2439 :             numer = r_int128 * b + a1;
                              10250                 :           2439 :             denom = 2 * s_int128;
                              10251                 :           2439 :             q = numer / denom;
                              10252                 :           2439 :             u = numer - q * denom;
                              10253                 :                : 
                              10254                 :                :             /* Compute s = s*b + q and r = u*b + a0 - q^2 */
                              10255                 :           2439 :             s_int128 = s_int128 * b + q;
                              10256                 :           2439 :             r_int128 = u * b + a0 - q * q;
                              10257                 :                : 
                              10258         [ +  + ]:           2439 :             if (r_int128 < 0)
                              10259                 :                :             {
                              10260                 :                :                 /* s is too large by 1; set r += s, s--, r += s */
                              10261                 :             96 :                 r_int128 += s_int128;
                              10262                 :             96 :                 s_int128--;
                              10263                 :             96 :                 r_int128 += s_int128;
                              10264                 :                :             }
                              10265                 :                : 
                              10266         [ -  + ]:           2439 :             Assert(src_idx == src_ndigits); /* All input digits consumed */
                              10267                 :           2439 :             step--;
                              10268                 :                :         }
                              10269                 :                : 
                              10270                 :                :         /*
                              10271                 :                :          * All remaining iterations require numeric variables.  Convert the
                              10272                 :                :          * integer values to NumericVar and continue.  Note that in the final
                              10273                 :                :          * iteration we don't need the remainder, so we can save a few cycles
                              10274                 :                :          * there by not fully computing it.
                              10275                 :                :          */
                              10276                 :           2085 :         int128_to_numericvar(s_int128, &s_var);
                              10277         [ +  + ]:           2085 :         if (step >= 0)
                              10278                 :           1362 :             int128_to_numericvar(r_int128, &r_var);
                              10279                 :                :     }
                              10280                 :                :     else
                              10281                 :                :     {
 1988 dean.a.rasheed@gmail    10282                 :UBC           0 :         int64_to_numericvar(s_int64, &s_var);
                              10283                 :                :         /* step < 0, so we certainly don't need r */
                              10284                 :                :     }
                              10285                 :                : #else                           /* !HAVE_INT128 */
                              10286                 :                :     int64_to_numericvar(s_int64, &s_var);
                              10287                 :                :     if (step >= 0)
                              10288                 :                :         int64_to_numericvar(r_int64, &r_var);
                              10289                 :                : #endif                          /* HAVE_INT128 */
                              10290                 :                : 
                              10291                 :                :     /*
                              10292                 :                :      * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
                              10293                 :                :      * use numeric variables.
                              10294                 :                :      */
 1988 dean.a.rasheed@gmail    10295         [ +  + ]:CBC        4344 :     while (step >= 0)
                              10296                 :                :     {
                              10297                 :                :         int         tmp_len;
                              10298                 :                : 
                              10299                 :           2259 :         src_ndigits = ndigits[step];
                              10300                 :           2259 :         blen = (src_ndigits - src_idx) / 2;
                              10301                 :                : 
                              10302                 :                :         /* Extract a1 and a0 */
                              10303         [ +  + ]:           2259 :         if (src_idx < arg->ndigits)
                              10304                 :                :         {
                              10305                 :            756 :             tmp_len = Min(blen, arg->ndigits - src_idx);
                              10306                 :            756 :             alloc_var(&a1_var, tmp_len);
                              10307                 :            756 :             memcpy(a1_var.digits, arg->digits + src_idx,
                              10308                 :                :                    tmp_len * sizeof(NumericDigit));
                              10309                 :            756 :             a1_var.weight = blen - 1;
                              10310                 :            756 :             a1_var.sign = NUMERIC_POS;
                              10311                 :            756 :             a1_var.dscale = 0;
                              10312                 :            756 :             strip_var(&a1_var);
                              10313                 :                :         }
                              10314                 :                :         else
                              10315                 :                :         {
                              10316                 :           1503 :             zero_var(&a1_var);
                              10317                 :           1503 :             a1_var.dscale = 0;
                              10318                 :                :         }
                              10319                 :           2259 :         src_idx += blen;
                              10320                 :                : 
                              10321         [ +  + ]:           2259 :         if (src_idx < arg->ndigits)
                              10322                 :                :         {
                              10323                 :            756 :             tmp_len = Min(blen, arg->ndigits - src_idx);
                              10324                 :            756 :             alloc_var(&a0_var, tmp_len);
                              10325                 :            756 :             memcpy(a0_var.digits, arg->digits + src_idx,
                              10326                 :                :                    tmp_len * sizeof(NumericDigit));
                              10327                 :            756 :             a0_var.weight = blen - 1;
                              10328                 :            756 :             a0_var.sign = NUMERIC_POS;
                              10329                 :            756 :             a0_var.dscale = 0;
                              10330                 :            756 :             strip_var(&a0_var);
                              10331                 :                :         }
                              10332                 :                :         else
                              10333                 :                :         {
                              10334                 :           1503 :             zero_var(&a0_var);
                              10335                 :           1503 :             a0_var.dscale = 0;
                              10336                 :                :         }
                              10337                 :           2259 :         src_idx += blen;
                              10338                 :                : 
                              10339                 :                :         /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
                              10340                 :           2259 :         set_var_from_var(&r_var, &q_var);
                              10341                 :           2259 :         q_var.weight += blen;
                              10342                 :           2259 :         add_var(&q_var, &a1_var, &q_var);
                              10343                 :           2259 :         add_var(&s_var, &s_var, &u_var);
                              10344                 :           2259 :         div_mod_var(&q_var, &u_var, &q_var, &u_var);
                              10345                 :                : 
                              10346                 :                :         /* Compute s = s*b + q */
                              10347                 :           2259 :         s_var.weight += blen;
                              10348                 :           2259 :         add_var(&s_var, &q_var, &s_var);
                              10349                 :                : 
                              10350                 :                :         /*
                              10351                 :                :          * Compute r = u*b + a0 - q^2.
                              10352                 :                :          *
                              10353                 :                :          * In the final iteration, we don't actually need r; we just need to
                              10354                 :                :          * know whether it is negative, so that we know whether to adjust s.
                              10355                 :                :          * So instead of the final subtraction we can just compare.
                              10356                 :                :          */
                              10357                 :           2259 :         u_var.weight += blen;
                              10358                 :           2259 :         add_var(&u_var, &a0_var, &u_var);
                              10359                 :           2259 :         mul_var(&q_var, &q_var, &q_var, 0);
                              10360                 :                : 
                              10361         [ +  + ]:           2259 :         if (step > 0)
                              10362                 :                :         {
                              10363                 :                :             /* Need r for later iterations */
                              10364                 :            897 :             sub_var(&u_var, &q_var, &r_var);
                              10365         [ +  + ]:            897 :             if (r_var.sign == NUMERIC_NEG)
                              10366                 :                :             {
                              10367                 :                :                 /* s is too large by 1; set r += s, s--, r += s */
                              10368                 :             60 :                 add_var(&r_var, &s_var, &r_var);
                              10369                 :             60 :                 sub_var(&s_var, &const_one, &s_var);
                              10370                 :             60 :                 add_var(&r_var, &s_var, &r_var);
                              10371                 :                :             }
                              10372                 :                :         }
                              10373                 :                :         else
                              10374                 :                :         {
                              10375                 :                :             /* Don't need r anymore, except to test if s is too large by 1 */
                              10376         [ +  + ]:           1362 :             if (cmp_var(&u_var, &q_var) < 0)
                              10377                 :             18 :                 sub_var(&s_var, &const_one, &s_var);
                              10378                 :                :         }
                              10379                 :                : 
                              10380         [ -  + ]:           2259 :         Assert(src_idx == src_ndigits); /* All input digits consumed */
                              10381                 :           2259 :         step--;
                              10382                 :                :     }
                              10383                 :                : 
                              10384                 :                :     /*
                              10385                 :                :      * Construct the final result, rounding it to the requested precision.
                              10386                 :                :      */
                              10387                 :           2085 :     set_var_from_var(&s_var, result);
                              10388                 :           2085 :     result->weight = res_weight;
                              10389                 :           2085 :     result->sign = NUMERIC_POS;
                              10390                 :                : 
                              10391                 :                :     /* Round to target rscale (and set result->dscale) */
 8205 tgl@sss.pgh.pa.us       10392                 :           2085 :     round_var(result, rscale);
                              10393                 :                : 
                              10394                 :                :     /* Strip leading and trailing zeroes */
 1988 dean.a.rasheed@gmail    10395                 :           2085 :     strip_var(result);
                              10396                 :                : 
                              10397                 :           2085 :     free_var(&s_var);
                              10398                 :           2085 :     free_var(&r_var);
                              10399                 :           2085 :     free_var(&a0_var);
                              10400                 :           2085 :     free_var(&a1_var);
                              10401                 :           2085 :     free_var(&q_var);
                              10402                 :           2085 :     free_var(&u_var);
                              10403                 :                : }
                              10404                 :                : 
                              10405                 :                : 
                              10406                 :                : /*
                              10407                 :                :  * exp_var() -
                              10408                 :                :  *
                              10409                 :                :  *  Raise e to the power of x, computed to rscale fractional digits
                              10410                 :                :  */
                              10411                 :                : static void
 2918 andres@anarazel.de      10412                 :             90 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
                              10413                 :                : {
                              10414                 :                :     NumericVar  x;
                              10415                 :                :     NumericVar  elem;
                              10416                 :                :     int         ni;
                              10417                 :                :     double      val;
                              10418                 :                :     int         dweight;
                              10419                 :                :     int         ndiv2;
                              10420                 :                :     int         sig_digits;
                              10421                 :                :     int         local_rscale;
                              10422                 :                : 
 9747 JanWieck@Yahoo.com      10423                 :             90 :     init_var(&x);
 3584 tgl@sss.pgh.pa.us       10424                 :             90 :     init_var(&elem);
                              10425                 :                : 
 9747 JanWieck@Yahoo.com      10426                 :             90 :     set_var_from_var(arg, &x);
                              10427                 :                : 
                              10428                 :                :     /*
                              10429                 :                :      * Estimate the dweight of the result using floating point arithmetic, so
                              10430                 :                :      * that we can choose an appropriate local rscale for the calculation.
                              10431                 :                :      */
 3584 tgl@sss.pgh.pa.us       10432                 :             90 :     val = numericvar_to_double_no_overflow(&x);
                              10433                 :                : 
                              10434                 :                :     /* Guard against overflow/underflow */
                              10435                 :                :     /* If you change this limit, see also power_var()'s limit */
 1065 peter@eisentraut.org    10436         [ +  + ]:             90 :     if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
                              10437                 :                :     {
 1498 dean.a.rasheed@gmail    10438         [ -  + ]:              3 :         if (val > 0)
 1498 dean.a.rasheed@gmail    10439         [ #  # ]:UBC           0 :             ereport(ERROR,
                              10440                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              10441                 :                :                      errmsg("value overflows numeric format")));
 1498 dean.a.rasheed@gmail    10442                 :CBC           3 :         zero_var(result);
                              10443                 :              3 :         result->dscale = rscale;
                              10444                 :              3 :         return;
                              10445                 :                :     }
                              10446                 :                : 
                              10447                 :                :     /* decimal weight = log10(e^x) = x * log10(e) */
 3584 tgl@sss.pgh.pa.us       10448                 :             87 :     dweight = (int) (val * 0.434294481903252);
                              10449                 :                : 
                              10450                 :                :     /*
                              10451                 :                :      * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
                              10452                 :                :      * 2^ndiv2, to improve the convergence rate of the Taylor series.
                              10453                 :                :      *
                              10454                 :                :      * Note that the overflow check above ensures that fabs(x) < 6000, which
                              10455                 :                :      * means that ndiv2 <= 20 here.
                              10456                 :                :      */
 1065 peter@eisentraut.org    10457         [ +  + ]:             87 :     if (fabs(val) > 0.01)
                              10458                 :                :     {
 3584 tgl@sss.pgh.pa.us       10459                 :             72 :         ndiv2 = 1;
                              10460                 :             72 :         val /= 2;
                              10461                 :                : 
 1065 peter@eisentraut.org    10462         [ +  + ]:            909 :         while (fabs(val) > 0.01)
                              10463                 :                :         {
 3584 tgl@sss.pgh.pa.us       10464                 :            837 :             ndiv2++;
                              10465                 :            837 :             val /= 2;
                              10466                 :                :         }
                              10467                 :                : 
                              10468                 :             72 :         local_rscale = x.dscale + ndiv2;
 1287 dean.a.rasheed@gmail    10469                 :             72 :         div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
                              10470                 :                :     }
                              10471                 :                :     else
 3584 tgl@sss.pgh.pa.us       10472                 :             15 :         ndiv2 = 0;
                              10473                 :                : 
                              10474                 :                :     /*
                              10475                 :                :      * Set the scale for the Taylor series expansion.  The final result has
                              10476                 :                :      * (dweight + rscale + 1) significant digits.  In addition, we have to
                              10477                 :                :      * raise the Taylor series result to the power 2^ndiv2, which introduces
                              10478                 :                :      * an error of up to around log10(2^ndiv2) digits, so work with this many
                              10479                 :                :      * extra digits of precision (plus a few more for good measure).
                              10480                 :                :      */
                              10481                 :             87 :     sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
                              10482                 :             87 :     sig_digits = Max(sig_digits, 0) + 8;
                              10483                 :                : 
                              10484                 :             87 :     local_rscale = sig_digits - 1;
                              10485                 :                : 
                              10486                 :                :     /*
                              10487                 :                :      * Use the Taylor series
                              10488                 :                :      *
                              10489                 :                :      * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
                              10490                 :                :      *
                              10491                 :                :      * Given the limited range of x, this should converge reasonably quickly.
                              10492                 :                :      * We run the series until the terms fall below the local_rscale limit.
                              10493                 :                :      */
 9747 JanWieck@Yahoo.com      10494                 :             87 :     add_var(&const_one, &x, result);
                              10495                 :                : 
 3584 tgl@sss.pgh.pa.us       10496                 :             87 :     mul_var(&x, &x, &elem, local_rscale);
 1287 dean.a.rasheed@gmail    10497                 :             87 :     ni = 2;
                              10498                 :             87 :     div_var_int(&elem, ni, 0, &elem, local_rscale, true);
                              10499                 :                : 
 3584 tgl@sss.pgh.pa.us       10500         [ +  + ]:           2496 :     while (elem.ndigits != 0)
                              10501                 :                :     {
 9747 JanWieck@Yahoo.com      10502                 :           2409 :         add_var(result, &elem, result);
                              10503                 :                : 
 3584 tgl@sss.pgh.pa.us       10504                 :           2409 :         mul_var(&elem, &x, &elem, local_rscale);
 1287 dean.a.rasheed@gmail    10505                 :           2409 :         ni++;
                              10506                 :           2409 :         div_var_int(&elem, ni, 0, &elem, local_rscale, true);
                              10507                 :                :     }
                              10508                 :                : 
                              10509                 :                :     /*
                              10510                 :                :      * Compensate for the argument range reduction.  Since the weight of the
                              10511                 :                :      * result doubles with each multiplication, we can reduce the local rscale
                              10512                 :                :      * as we proceed.
                              10513                 :                :      */
 9747 JanWieck@Yahoo.com      10514         [ +  + ]:            996 :     while (ndiv2-- > 0)
                              10515                 :                :     {
 3584 tgl@sss.pgh.pa.us       10516                 :            909 :         local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
                              10517                 :            909 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
 8205                         10518                 :            909 :         mul_var(result, result, result, local_rscale);
                              10519                 :                :     }
                              10520                 :                : 
                              10521                 :                :     /* Round to requested rscale */
 3584                         10522                 :             87 :     round_var(result, rscale);
                              10523                 :                : 
 9747 JanWieck@Yahoo.com      10524                 :             87 :     free_var(&x);
                              10525                 :             87 :     free_var(&elem);
                              10526                 :                : }
                              10527                 :                : 
                              10528                 :                : 
                              10529                 :                : /*
                              10530                 :                :  * Estimate the dweight of the most significant decimal digit of the natural
                              10531                 :                :  * logarithm of a number.
                              10532                 :                :  *
                              10533                 :                :  * Essentially, we're approximating log10(abs(ln(var))).  This is used to
                              10534                 :                :  * determine the appropriate rscale when computing natural logarithms.
                              10535                 :                :  *
                              10536                 :                :  * Note: many callers call this before range-checking the input.  Therefore,
                              10537                 :                :  * we must be robust against values that are invalid to apply ln() to.
                              10538                 :                :  * We don't wish to throw an error here, so just return zero in such cases.
                              10539                 :                :  */
                              10540                 :                : static int
 2918 andres@anarazel.de      10541                 :            369 : estimate_ln_dweight(const NumericVar *var)
                              10542                 :                : {
                              10543                 :                :     int         ln_dweight;
                              10544                 :                : 
                              10545                 :                :     /* Caller should fail on ln(negative), but for the moment return zero */
 1283 tgl@sss.pgh.pa.us       10546         [ +  + ]:            369 :     if (var->sign != NUMERIC_POS)
                              10547                 :             21 :         return 0;
                              10548                 :                : 
 3584                         10549   [ +  +  +  + ]:            657 :     if (cmp_var(var, &const_zero_point_nine) >= 0 &&
                              10550                 :            309 :         cmp_var(var, &const_one_point_one) <= 0)
                              10551                 :             45 :     {
                              10552                 :                :         /*
                              10553                 :                :          * 0.9 <= var <= 1.1
                              10554                 :                :          *
                              10555                 :                :          * ln(var) has a negative weight (possibly very large).  To get a
                              10556                 :                :          * reasonably accurate result, estimate it using ln(1+x) ~= x.
                              10557                 :                :          */
                              10558                 :                :         NumericVar  x;
                              10559                 :                : 
                              10560                 :             45 :         init_var(&x);
                              10561                 :             45 :         sub_var(var, &const_one, &x);
                              10562                 :                : 
                              10563         [ +  + ]:             45 :         if (x.ndigits > 0)
                              10564                 :                :         {
                              10565                 :                :             /* Use weight of most significant decimal digit of x */
                              10566                 :             21 :             ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
                              10567                 :                :         }
                              10568                 :                :         else
                              10569                 :                :         {
                              10570                 :                :             /* x = 0.  Since ln(1) = 0 exactly, we don't need extra digits */
                              10571                 :             24 :             ln_dweight = 0;
                              10572                 :                :         }
                              10573                 :                : 
                              10574                 :             45 :         free_var(&x);
                              10575                 :                :     }
                              10576                 :                :     else
                              10577                 :                :     {
                              10578                 :                :         /*
                              10579                 :                :          * Estimate the logarithm using the first couple of digits from the
                              10580                 :                :          * input number.  This will give an accurate result whenever the input
                              10581                 :                :          * is not too close to 1.
                              10582                 :                :          */
                              10583         [ +  + ]:            303 :         if (var->ndigits > 0)
                              10584                 :                :         {
                              10585                 :                :             int         digits;
                              10586                 :                :             int         dweight;
                              10587                 :                :             double      ln_var;
                              10588                 :                : 
                              10589                 :            282 :             digits = var->digits[0];
                              10590                 :            282 :             dweight = var->weight * DEC_DIGITS;
                              10591                 :                : 
                              10592         [ +  + ]:            282 :             if (var->ndigits > 1)
                              10593                 :                :             {
                              10594                 :            171 :                 digits = digits * NBASE + var->digits[1];
                              10595                 :            171 :                 dweight -= DEC_DIGITS;
                              10596                 :                :             }
                              10597                 :                : 
                              10598                 :                :             /*----------
                              10599                 :                :              * We have var ~= digits * 10^dweight
                              10600                 :                :              * so ln(var) ~= ln(digits) + dweight * ln(10)
                              10601                 :                :              *----------
                              10602                 :                :              */
                              10603                 :            282 :             ln_var = log((double) digits) + dweight * 2.302585092994046;
 1065 peter@eisentraut.org    10604                 :            282 :             ln_dweight = (int) log10(fabs(ln_var));
                              10605                 :                :         }
                              10606                 :                :         else
                              10607                 :                :         {
                              10608                 :                :             /* Caller should fail on ln(0), but for the moment return zero */
 3584 tgl@sss.pgh.pa.us       10609                 :             21 :             ln_dweight = 0;
                              10610                 :                :         }
                              10611                 :                :     }
                              10612                 :                : 
                              10613                 :            348 :     return ln_dweight;
                              10614                 :                : }
                              10615                 :                : 
                              10616                 :                : 
                              10617                 :                : /*
                              10618                 :                :  * ln_var() -
                              10619                 :                :  *
                              10620                 :                :  *  Compute the natural log of x
                              10621                 :                :  */
                              10622                 :                : static void
 2918 andres@anarazel.de      10623                 :            417 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
                              10624                 :                : {
                              10625                 :                :     NumericVar  x;
                              10626                 :                :     NumericVar  xx;
                              10627                 :                :     int         ni;
                              10628                 :                :     NumericVar  elem;
                              10629                 :                :     NumericVar  fact;
                              10630                 :                :     int         nsqrt;
                              10631                 :                :     int         local_rscale;
                              10632                 :                :     int         cmp;
                              10633                 :                : 
 7783 neilc@samurai.com       10634                 :            417 :     cmp = cmp_var(arg, &const_zero);
                              10635         [ +  + ]:            417 :     if (cmp == 0)
 8077 tgl@sss.pgh.pa.us       10636         [ +  - ]:             21 :         ereport(ERROR,
                              10637                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                              10638                 :                :                  errmsg("cannot take logarithm of zero")));
 7783 neilc@samurai.com       10639         [ +  + ]:            396 :     else if (cmp < 0)
                              10640         [ +  - ]:             18 :         ereport(ERROR,
                              10641                 :                :                 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
                              10642                 :                :                  errmsg("cannot take logarithm of a negative number")));
                              10643                 :                : 
 9747 JanWieck@Yahoo.com      10644                 :            378 :     init_var(&x);
                              10645                 :            378 :     init_var(&xx);
                              10646                 :            378 :     init_var(&elem);
                              10647                 :            378 :     init_var(&fact);
                              10648                 :                : 
                              10649                 :            378 :     set_var_from_var(arg, &x);
 8205 tgl@sss.pgh.pa.us       10650                 :            378 :     set_var_from_var(&const_two, &fact);
                              10651                 :                : 
                              10652                 :                :     /*
                              10653                 :                :      * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
                              10654                 :                :      *
                              10655                 :                :      * The final logarithm will have up to around rscale+6 significant digits.
                              10656                 :                :      * Each sqrt() will roughly halve the weight of x, so adjust the local
                              10657                 :                :      * rscale as we work so that we keep this many significant digits at each
                              10658                 :                :      * step (plus a few more for good measure).
                              10659                 :                :      *
                              10660                 :                :      * Note that we allow local_rscale < 0 during this input reduction
                              10661                 :                :      * process, which implies rounding before the decimal point.  sqrt_var()
                              10662                 :                :      * explicitly supports this, and it significantly reduces the work
                              10663                 :                :      * required to reduce very large inputs to the required range.  Once the
                              10664                 :                :      * input reduction is complete, x.weight will be 0 and its display scale
                              10665                 :                :      * will be non-negative again.
                              10666                 :                :      */
 2015 dean.a.rasheed@gmail    10667                 :            378 :     nsqrt = 0;
 8375 tgl@sss.pgh.pa.us       10668         [ +  + ]:            534 :     while (cmp_var(&x, &const_zero_point_nine) <= 0)
                              10669                 :                :     {
 3584                         10670                 :            156 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
 8205                         10671                 :            156 :         sqrt_var(&x, &x, local_rscale);
                              10672                 :            156 :         mul_var(&fact, &const_two, &fact, 0);
 2015 dean.a.rasheed@gmail    10673                 :            156 :         nsqrt++;
                              10674                 :                :     }
 8375 tgl@sss.pgh.pa.us       10675         [ +  + ]:           2064 :     while (cmp_var(&x, &const_one_point_one) >= 0)
                              10676                 :                :     {
 3584                         10677                 :           1686 :         local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
 8205                         10678                 :           1686 :         sqrt_var(&x, &x, local_rscale);
                              10679                 :           1686 :         mul_var(&fact, &const_two, &fact, 0);
 2015 dean.a.rasheed@gmail    10680                 :           1686 :         nsqrt++;
                              10681                 :                :     }
                              10682                 :                : 
                              10683                 :                :     /*
                              10684                 :                :      * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
                              10685                 :                :      *
                              10686                 :                :      * z + z^3/3 + z^5/5 + ...
                              10687                 :                :      *
                              10688                 :                :      * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
                              10689                 :                :      * due to the above range-reduction of x.
                              10690                 :                :      *
                              10691                 :                :      * The convergence of this is not as fast as one would like, but is
                              10692                 :                :      * tolerable given that z is small.
                              10693                 :                :      *
                              10694                 :                :      * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
                              10695                 :                :      * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
                              10696                 :                :      * digits of precision (plus a few more for good measure).
                              10697                 :                :      */
                              10698                 :            378 :     local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
                              10699                 :                : 
 9747 JanWieck@Yahoo.com      10700                 :            378 :     sub_var(&x, &const_one, result);
                              10701                 :            378 :     add_var(&x, &const_one, &elem);
  337 dean.a.rasheed@gmail    10702                 :            378 :     div_var(result, &elem, result, local_rscale, true, false);
 9747 JanWieck@Yahoo.com      10703                 :            378 :     set_var_from_var(result, &xx);
 8205 tgl@sss.pgh.pa.us       10704                 :            378 :     mul_var(result, result, &x, local_rscale);
                              10705                 :                : 
 1287 dean.a.rasheed@gmail    10706                 :            378 :     ni = 1;
                              10707                 :                : 
                              10708                 :                :     for (;;)
                              10709                 :                :     {
                              10710                 :           7011 :         ni += 2;
 8205 tgl@sss.pgh.pa.us       10711                 :           7011 :         mul_var(&xx, &x, &xx, local_rscale);
 1287 dean.a.rasheed@gmail    10712                 :           7011 :         div_var_int(&xx, ni, 0, &elem, local_rscale, true);
                              10713                 :                : 
 8375 tgl@sss.pgh.pa.us       10714         [ +  + ]:           7011 :         if (elem.ndigits == 0)
 9747 JanWieck@Yahoo.com      10715                 :            378 :             break;
                              10716                 :                : 
                              10717                 :           6633 :         add_var(result, &elem, result);
                              10718                 :                : 
 8069 bruce@momjian.us        10719         [ -  + ]:           6633 :         if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
 8212 tgl@sss.pgh.pa.us       10720                 :UBC           0 :             break;
                              10721                 :                :     }
                              10722                 :                : 
                              10723                 :                :     /* Compensate for argument range reduction, round to requested rscale */
 8205 tgl@sss.pgh.pa.us       10724                 :CBC         378 :     mul_var(result, &fact, result, rscale);
                              10725                 :                : 
 9747 JanWieck@Yahoo.com      10726                 :            378 :     free_var(&x);
                              10727                 :            378 :     free_var(&xx);
                              10728                 :            378 :     free_var(&elem);
                              10729                 :            378 :     free_var(&fact);
                              10730                 :            378 : }
                              10731                 :                : 
                              10732                 :                : 
                              10733                 :                : /*
                              10734                 :                :  * log_var() -
                              10735                 :                :  *
                              10736                 :                :  *  Compute the logarithm of num in a given base.
                              10737                 :                :  *
                              10738                 :                :  *  Note: this routine chooses dscale of the result.
                              10739                 :                :  */
                              10740                 :                : static void
 2918 andres@anarazel.de      10741                 :            108 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
                              10742                 :                : {
                              10743                 :                :     NumericVar  ln_base;
                              10744                 :                :     NumericVar  ln_num;
                              10745                 :                :     int         ln_base_dweight;
                              10746                 :                :     int         ln_num_dweight;
                              10747                 :                :     int         result_dweight;
                              10748                 :                :     int         rscale;
                              10749                 :                :     int         ln_base_rscale;
                              10750                 :                :     int         ln_num_rscale;
                              10751                 :                : 
 9747 JanWieck@Yahoo.com      10752                 :            108 :     init_var(&ln_base);
                              10753                 :            108 :     init_var(&ln_num);
                              10754                 :                : 
                              10755                 :                :     /* Estimated dweights of ln(base), ln(num) and the final result */
 3584 tgl@sss.pgh.pa.us       10756                 :            108 :     ln_base_dweight = estimate_ln_dweight(base);
                              10757                 :            108 :     ln_num_dweight = estimate_ln_dweight(num);
                              10758                 :            108 :     result_dweight = ln_num_dweight - ln_base_dweight;
                              10759                 :                : 
                              10760                 :                :     /*
                              10761                 :                :      * Select the scale of the result so that it will have at least
                              10762                 :                :      * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
                              10763                 :                :      * input's display scale.
                              10764                 :                :      */
                              10765                 :            108 :     rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
 8205                         10766                 :            108 :     rscale = Max(rscale, base->dscale);
                              10767                 :            108 :     rscale = Max(rscale, num->dscale);
                              10768                 :            108 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10769                 :            108 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                              10770                 :                : 
                              10771                 :                :     /*
                              10772                 :                :      * Set the scales for ln(base) and ln(num) so that they each have more
                              10773                 :                :      * significant digits than the final result.
                              10774                 :                :      */
 3584                         10775                 :            108 :     ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
                              10776                 :            108 :     ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10777                 :                : 
                              10778                 :            108 :     ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
                              10779                 :            108 :     ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10780                 :                : 
                              10781                 :                :     /* Form natural logarithms */
                              10782                 :            108 :     ln_var(base, &ln_base, ln_base_rscale);
                              10783                 :             96 :     ln_var(num, &ln_num, ln_num_rscale);
                              10784                 :                : 
                              10785                 :                :     /* Divide and round to the required scale */
  337 dean.a.rasheed@gmail    10786                 :             81 :     div_var(&ln_num, &ln_base, result, rscale, true, false);
                              10787                 :                : 
 9747 JanWieck@Yahoo.com      10788                 :             78 :     free_var(&ln_num);
                              10789                 :             78 :     free_var(&ln_base);
                              10790                 :             78 : }
                              10791                 :                : 
                              10792                 :                : 
                              10793                 :                : /*
                              10794                 :                :  * power_var() -
                              10795                 :                :  *
                              10796                 :                :  *  Raise base to the power of exp
                              10797                 :                :  *
                              10798                 :                :  *  Note: this routine chooses dscale of the result.
                              10799                 :                :  */
                              10800                 :                : static void
 2918 andres@anarazel.de      10801                 :            699 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
                              10802                 :                : {
                              10803                 :                :     int         res_sign;
                              10804                 :                :     NumericVar  abs_base;
                              10805                 :                :     NumericVar  ln_base;
                              10806                 :                :     NumericVar  ln_num;
                              10807                 :                :     int         ln_dweight;
                              10808                 :                :     int         rscale;
                              10809                 :                :     int         sig_digits;
                              10810                 :                :     int         local_rscale;
                              10811                 :                :     double      val;
                              10812                 :                : 
                              10813                 :                :     /* If exp can be represented as an integer, use power_var_int */
 8205 tgl@sss.pgh.pa.us       10814   [ +  +  +  + ]:            699 :     if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
                              10815                 :                :     {
                              10816                 :                :         /* exact integer, but does it fit in int? */
                              10817                 :                :         int64       expval64;
                              10818                 :                : 
 3823 andres@anarazel.de      10819         [ +  + ]:            636 :         if (numericvar_to_int64(exp, &expval64))
                              10820                 :                :         {
 1492 dean.a.rasheed@gmail    10821   [ +  -  +  + ]:            633 :             if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
                              10822                 :                :             {
                              10823                 :                :                 /* Okay, use power_var_int */
 1052                         10824                 :            618 :                 power_var_int(base, (int) expval64, exp->dscale, result);
 8205 tgl@sss.pgh.pa.us       10825                 :            612 :                 return;
                              10826                 :                :             }
                              10827                 :                :         }
                              10828                 :                :     }
                              10829                 :                : 
                              10830                 :                :     /*
                              10831                 :                :      * This avoids log(0) for cases of 0 raised to a non-integer.  0 ^ 0 is
                              10832                 :                :      * handled by power_var_int().
                              10833                 :                :      */
 6330 bruce@momjian.us        10834         [ +  + ]:             81 :     if (cmp_var(base, &const_zero) == 0)
                              10835                 :                :     {
                              10836                 :              9 :         set_var_from_var(&const_zero, result);
 2999 tgl@sss.pgh.pa.us       10837                 :              9 :         result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
 6330 bruce@momjian.us        10838                 :              9 :         return;
                              10839                 :                :     }
                              10840                 :                : 
 1498 dean.a.rasheed@gmail    10841                 :             72 :     init_var(&abs_base);
 9747 JanWieck@Yahoo.com      10842                 :             72 :     init_var(&ln_base);
                              10843                 :             72 :     init_var(&ln_num);
                              10844                 :                : 
                              10845                 :                :     /*
                              10846                 :                :      * If base is negative, insist that exp be an integer.  The result is then
                              10847                 :                :      * positive if exp is even and negative if exp is odd.
                              10848                 :                :      */
 1498 dean.a.rasheed@gmail    10849         [ +  + ]:             72 :     if (base->sign == NUMERIC_NEG)
                              10850                 :                :     {
                              10851                 :                :         /*
                              10852                 :                :          * Check that exp is an integer.  This error code is defined by the
                              10853                 :                :          * SQL standard, and matches other errors in numeric_power().
                              10854                 :                :          */
                              10855   [ +  -  +  + ]:             18 :         if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
                              10856         [ +  - ]:              9 :             ereport(ERROR,
                              10857                 :                :                     (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
                              10858                 :                :                      errmsg("a negative number raised to a non-integer power yields a complex result")));
                              10859                 :                : 
                              10860                 :                :         /* Test if exp is odd or even */
                              10861   [ +  -  +  + ]:              9 :         if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
                              10862         [ +  + ]:              6 :             (exp->digits[exp->ndigits - 1] & 1))
                              10863                 :              3 :             res_sign = NUMERIC_NEG;
                              10864                 :                :         else
                              10865                 :              6 :             res_sign = NUMERIC_POS;
                              10866                 :                : 
                              10867                 :                :         /* Then work with abs(base) below */
                              10868                 :              9 :         set_var_from_var(base, &abs_base);
                              10869                 :              9 :         abs_base.sign = NUMERIC_POS;
                              10870                 :              9 :         base = &abs_base;
                              10871                 :                :     }
                              10872                 :                :     else
                              10873                 :             54 :         res_sign = NUMERIC_POS;
                              10874                 :                : 
                              10875                 :                :     /*----------
                              10876                 :                :      * Decide on the scale for the ln() calculation.  For this we need an
                              10877                 :                :      * estimate of the weight of the result, which we obtain by doing an
                              10878                 :                :      * initial low-precision calculation of exp * ln(base).
                              10879                 :                :      *
                              10880                 :                :      * We want result = e ^ (exp * ln(base))
                              10881                 :                :      * so result dweight = log10(result) = exp * ln(base) * log10(e)
                              10882                 :                :      *
                              10883                 :                :      * We also perform a crude overflow test here so that we can exit early if
                              10884                 :                :      * the full-precision result is sure to overflow, and to guard against
                              10885                 :                :      * integer overflow when determining the scale for the real calculation.
                              10886                 :                :      * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
                              10887                 :                :      * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
                              10888                 :                :      * Since the values here are only approximations, we apply a small fuzz
                              10889                 :                :      * factor to this overflow test and let exp_var() determine the exact
                              10890                 :                :      * overflow threshold so that it is consistent for all inputs.
                              10891                 :                :      *----------
                              10892                 :                :      */
 3584 tgl@sss.pgh.pa.us       10893                 :             63 :     ln_dweight = estimate_ln_dweight(base);
                              10894                 :                : 
                              10895                 :                :     /*
                              10896                 :                :      * Set the scale for the low-precision calculation, computing ln(base) to
                              10897                 :                :      * around 8 significant digits.  Note that ln_dweight may be as small as
                              10898                 :                :      * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
                              10899                 :                :      * here.
                              10900                 :                :      */
                              10901                 :             63 :     local_rscale = 8 - ln_dweight;
                              10902                 :             63 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10903                 :                : 
 8205                         10904                 :             63 :     ln_var(base, &ln_base, local_rscale);
                              10905                 :                : 
                              10906                 :             63 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
                              10907                 :                : 
 8375                         10908                 :             63 :     val = numericvar_to_double_no_overflow(&ln_num);
                              10909                 :                : 
                              10910                 :                :     /* initial overflow/underflow test with fuzz factor */
 1065 peter@eisentraut.org    10911         [ +  + ]:             63 :     if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
                              10912                 :                :     {
 1498 dean.a.rasheed@gmail    10913         [ -  + ]:              3 :         if (val > 0)
 1498 dean.a.rasheed@gmail    10914         [ #  # ]:UBC           0 :             ereport(ERROR,
                              10915                 :                :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              10916                 :                :                      errmsg("value overflows numeric format")));
 1498 dean.a.rasheed@gmail    10917                 :CBC           3 :         zero_var(result);
                              10918                 :              3 :         result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
                              10919                 :              3 :         return;
                              10920                 :                :     }
                              10921                 :                : 
 3411                         10922                 :             60 :     val *= 0.434294481903252;   /* approximate decimal result weight */
                              10923                 :                : 
                              10924                 :                :     /* choose the result scale */
 8205 tgl@sss.pgh.pa.us       10925                 :             60 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
                              10926                 :             60 :     rscale = Max(rscale, base->dscale);
                              10927                 :             60 :     rscale = Max(rscale, exp->dscale);
                              10928                 :             60 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10929                 :             60 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                              10930                 :                : 
                              10931                 :                :     /* significant digits required in the result */
 1498 dean.a.rasheed@gmail    10932                 :             60 :     sig_digits = rscale + (int) val;
                              10933                 :             60 :     sig_digits = Max(sig_digits, 0);
                              10934                 :                : 
                              10935                 :                :     /* set the scale for the real exp * ln(base) calculation */
                              10936                 :             60 :     local_rscale = sig_digits - ln_dweight + 8;
 3584 tgl@sss.pgh.pa.us       10937                 :             60 :     local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              10938                 :                : 
                              10939                 :                :     /* and do the real calculation */
                              10940                 :                : 
                              10941                 :             60 :     ln_var(base, &ln_base, local_rscale);
                              10942                 :                : 
                              10943                 :             60 :     mul_var(&ln_base, exp, &ln_num, local_rscale);
                              10944                 :                : 
 8205                         10945                 :             60 :     exp_var(&ln_num, result, rscale);
                              10946                 :                : 
 1498 dean.a.rasheed@gmail    10947   [ +  +  +  - ]:             60 :     if (res_sign == NUMERIC_NEG && result->ndigits > 0)
                              10948                 :              3 :         result->sign = NUMERIC_NEG;
                              10949                 :                : 
 8205 tgl@sss.pgh.pa.us       10950                 :             60 :     free_var(&ln_num);
                              10951                 :             60 :     free_var(&ln_base);
 1498 dean.a.rasheed@gmail    10952                 :             60 :     free_var(&abs_base);
                              10953                 :                : }
                              10954                 :                : 
                              10955                 :                : /*
                              10956                 :                :  * power_var_int() -
                              10957                 :                :  *
                              10958                 :                :  *  Raise base to the power of exp, where exp is an integer.
                              10959                 :                :  *
                              10960                 :                :  *  Note: this routine chooses dscale of the result.
                              10961                 :                :  */
                              10962                 :                : static void
 1052                         10963                 :            618 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
                              10964                 :                :               NumericVar *result)
                              10965                 :                : {
                              10966                 :                :     double      f;
                              10967                 :                :     int         p;
                              10968                 :                :     int         i;
                              10969                 :                :     int         rscale;
                              10970                 :                :     int         sig_digits;
                              10971                 :                :     unsigned int mask;
                              10972                 :                :     bool        neg;
                              10973                 :                :     NumericVar  base_prod;
                              10974                 :                :     int         local_rscale;
                              10975                 :                : 
                              10976                 :                :     /*
                              10977                 :                :      * Choose the result scale.  For this we need an estimate of the decimal
                              10978                 :                :      * weight of the result, which we obtain by approximating using double
                              10979                 :                :      * precision arithmetic.
                              10980                 :                :      *
                              10981                 :                :      * We also perform crude overflow/underflow tests here so that we can exit
                              10982                 :                :      * early if the result is sure to overflow/underflow, and to guard against
                              10983                 :                :      * integer overflow when choosing the result scale.
                              10984                 :                :      */
                              10985         [ +  + ]:            618 :     if (base->ndigits != 0)
                              10986                 :                :     {
                              10987                 :                :         /*----------
                              10988                 :                :          * Choose f (double) and p (int) such that base ~= f * 10^p.
                              10989                 :                :          * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
                              10990                 :                :          *----------
                              10991                 :                :          */
                              10992                 :            603 :         f = base->digits[0];
                              10993                 :            603 :         p = base->weight * DEC_DIGITS;
                              10994                 :                : 
                              10995   [ +  +  +  - ]:            645 :         for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
                              10996                 :                :         {
                              10997                 :             42 :             f = f * NBASE + base->digits[i];
                              10998                 :             42 :             p -= DEC_DIGITS;
                              10999                 :                :         }
                              11000                 :                : 
                              11001                 :            603 :         f = exp * (log10(f) + p);   /* approximate decimal result weight */
                              11002                 :                :     }
                              11003                 :                :     else
                              11004                 :             15 :         f = 0;                  /* result is 0 or 1 (weight 0), or error */
                              11005                 :                : 
                              11006                 :                :     /* overflow/underflow tests with fuzz factors */
  425                         11007         [ +  + ]:            618 :     if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
 1052                         11008         [ +  - ]:              6 :         ereport(ERROR,
                              11009                 :                :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              11010                 :                :                  errmsg("value overflows numeric format")));
                              11011         [ +  + ]:            612 :     if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
                              11012                 :                :     {
                              11013                 :              6 :         zero_var(result);
                              11014                 :              6 :         result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
                              11015                 :            108 :         return;
                              11016                 :                :     }
                              11017                 :                : 
                              11018                 :                :     /*
                              11019                 :                :      * Choose the result scale in the same way as power_var(), so it has at
                              11020                 :                :      * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
                              11021                 :                :      * either input's display scale.
                              11022                 :                :      */
                              11023                 :            606 :     rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
                              11024                 :            606 :     rscale = Max(rscale, base->dscale);
                              11025                 :            606 :     rscale = Max(rscale, exp_dscale);
                              11026                 :            606 :     rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11027                 :            606 :     rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
                              11028                 :                : 
                              11029                 :                :     /* Handle some common special cases, as well as corner cases */
 8205 tgl@sss.pgh.pa.us       11030   [ +  +  +  +  :            606 :     switch (exp)
                                                 + ]
                              11031                 :                :     {
                              11032                 :             36 :         case 0:
                              11033                 :                : 
                              11034                 :                :             /*
                              11035                 :                :              * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
                              11036                 :                :              * it as 1 because most programming languages do this. SQL:2003
                              11037                 :                :              * also requires a return value of 1.
                              11038                 :                :              * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
                              11039                 :                :              */
                              11040                 :             36 :             set_var_from_var(&const_one, result);
 8069 bruce@momjian.us        11041                 :             36 :             result->dscale = rscale; /* no need to round */
 8205 tgl@sss.pgh.pa.us       11042                 :             36 :             return;
                              11043                 :             24 :         case 1:
                              11044                 :             24 :             set_var_from_var(base, result);
                              11045                 :             24 :             round_var(result, rscale);
                              11046                 :             24 :             return;
                              11047                 :             15 :         case -1:
  337 dean.a.rasheed@gmail    11048                 :             15 :             div_var(&const_one, base, result, rscale, true, true);
 8205 tgl@sss.pgh.pa.us       11049                 :             15 :             return;
                              11050                 :             27 :         case 2:
                              11051                 :             27 :             mul_var(base, base, result, rscale);
                              11052                 :             27 :             return;
                              11053                 :            504 :         default:
                              11054                 :            504 :             break;
                              11055                 :                :     }
                              11056                 :                : 
                              11057                 :                :     /* Handle the special case where the base is zero */
 3584                         11058         [ -  + ]:            504 :     if (base->ndigits == 0)
                              11059                 :                :     {
 3584 tgl@sss.pgh.pa.us       11060         [ #  # ]:UBC           0 :         if (exp < 0)
                              11061         [ #  # ]:              0 :             ereport(ERROR,
                              11062                 :                :                     (errcode(ERRCODE_DIVISION_BY_ZERO),
                              11063                 :                :                      errmsg("division by zero")));
                              11064                 :              0 :         zero_var(result);
                              11065                 :              0 :         result->dscale = rscale;
                              11066                 :              0 :         return;
                              11067                 :                :     }
                              11068                 :                : 
                              11069                 :                :     /*
                              11070                 :                :      * The general case repeatedly multiplies base according to the bit
                              11071                 :                :      * pattern of exp.
                              11072                 :                :      *
                              11073                 :                :      * The local rscale used for each multiplication is varied to keep a fixed
                              11074                 :                :      * number of significant digits, sufficient to give the required result
                              11075                 :                :      * scale.
                              11076                 :                :      */
                              11077                 :                : 
                              11078                 :                :     /*
                              11079                 :                :      * Approximate number of significant digits in the result.  Note that the
                              11080                 :                :      * underflow test above, together with the choice of rscale, ensures that
                              11081                 :                :      * this approximation is necessarily > 0.
                              11082                 :                :      */
 3584 tgl@sss.pgh.pa.us       11083                 :CBC         504 :     sig_digits = 1 + rscale + (int) f;
                              11084                 :                : 
                              11085                 :                :     /*
                              11086                 :                :      * The multiplications to produce the result may introduce an error of up
                              11087                 :                :      * to around log10(abs(exp)) digits, so work with this many extra digits
                              11088                 :                :      * of precision (plus a few more for good measure).
                              11089                 :                :      */
 1705 dean.a.rasheed@gmail    11090                 :            504 :     sig_digits += (int) log(fabs((double) exp)) + 8;
                              11091                 :                : 
                              11092                 :                :     /*
                              11093                 :                :      * Now we can proceed with the multiplications.
                              11094                 :                :      */
 8205 tgl@sss.pgh.pa.us       11095                 :            504 :     neg = (exp < 0);
  387 nathan@postgresql.or    11096                 :            504 :     mask = pg_abs_s32(exp);
                              11097                 :                : 
 8205 tgl@sss.pgh.pa.us       11098                 :            504 :     init_var(&base_prod);
                              11099                 :            504 :     set_var_from_var(base, &base_prod);
                              11100                 :                : 
 4013                         11101         [ +  + ]:            504 :     if (mask & 1)
 8205                         11102                 :            249 :         set_var_from_var(base, result);
                              11103                 :                :     else
                              11104                 :            255 :         set_var_from_var(&const_one, result);
                              11105                 :                : 
 4013                         11106         [ +  + ]:           2538 :     while ((mask >>= 1) > 0)
                              11107                 :                :     {
                              11108                 :                :         /*
                              11109                 :                :          * Do the multiplications using rscales large enough to hold the
                              11110                 :                :          * results to the required number of significant digits, but don't
                              11111                 :                :          * waste time by exceeding the scales of the numbers themselves.
                              11112                 :                :          */
 3584                         11113                 :           2034 :         local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
                              11114                 :           2034 :         local_rscale = Min(local_rscale, 2 * base_prod.dscale);
                              11115                 :           2034 :         local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11116                 :                : 
 8205                         11117                 :           2034 :         mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
                              11118                 :                : 
 4013                         11119         [ +  + ]:           2034 :         if (mask & 1)
                              11120                 :                :         {
 3584                         11121                 :           1329 :             local_rscale = sig_digits -
                              11122                 :           1329 :                 (base_prod.weight + result->weight) * DEC_DIGITS;
                              11123                 :           1329 :             local_rscale = Min(local_rscale,
                              11124                 :                :                                base_prod.dscale + result->dscale);
                              11125                 :           1329 :             local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
                              11126                 :                : 
 8205                         11127                 :           1329 :             mul_var(&base_prod, result, result, local_rscale);
                              11128                 :                :         }
                              11129                 :                : 
                              11130                 :                :         /*
                              11131                 :                :          * When abs(base) > 1, the number of digits to the left of the decimal
                              11132                 :                :          * point in base_prod doubles at each iteration, so if exp is large we
                              11133                 :                :          * could easily spend large amounts of time and memory space doing the
                              11134                 :                :          * multiplications.  But once the weight exceeds what will fit in
                              11135                 :                :          * int16, the final result is guaranteed to overflow (or underflow, if
                              11136                 :                :          * exp < 0), so we can give up before wasting too many cycles.
                              11137                 :                :          */
  425 dean.a.rasheed@gmail    11138         [ +  - ]:           2034 :         if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
                              11139         [ -  + ]:           2034 :             result->weight > NUMERIC_WEIGHT_MAX)
                              11140                 :                :         {
                              11141                 :                :             /* overflow, unless neg, in which case result should be 0 */
 4013 tgl@sss.pgh.pa.us       11142         [ #  # ]:UBC           0 :             if (!neg)
                              11143         [ #  # ]:              0 :                 ereport(ERROR,
                              11144                 :                :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                              11145                 :                :                          errmsg("value overflows numeric format")));
                              11146                 :              0 :             zero_var(result);
                              11147                 :              0 :             neg = false;
                              11148                 :              0 :             break;
                              11149                 :                :         }
                              11150                 :                :     }
                              11151                 :                : 
 8205 tgl@sss.pgh.pa.us       11152                 :CBC         504 :     free_var(&base_prod);
                              11153                 :                : 
                              11154                 :                :     /* Compensate for input sign, and round to requested rscale */
                              11155         [ +  + ]:            504 :     if (neg)
  337 dean.a.rasheed@gmail    11156                 :            243 :         div_var(&const_one, result, result, rscale, true, false);
                              11157                 :                :     else
 8205 tgl@sss.pgh.pa.us       11158                 :            261 :         round_var(result, rscale);
                              11159                 :                : }
                              11160                 :                : 
                              11161                 :                : /*
                              11162                 :                :  * power_ten_int() -
                              11163                 :                :  *
                              11164                 :                :  *  Raise ten to the power of exp, where exp is an integer.  Note that unlike
                              11165                 :                :  *  power_var_int(), this does no overflow/underflow checking or rounding.
                              11166                 :                :  */
                              11167                 :                : static void
 1493 dean.a.rasheed@gmail    11168                 :            114 : power_ten_int(int exp, NumericVar *result)
                              11169                 :                : {
                              11170                 :                :     /* Construct the result directly, starting from 10^0 = 1 */
                              11171                 :            114 :     set_var_from_var(&const_one, result);
                              11172                 :                : 
                              11173                 :                :     /* Scale needed to represent the result exactly */
                              11174         [ +  + ]:            114 :     result->dscale = exp < 0 ? -exp : 0;
                              11175                 :                : 
                              11176                 :                :     /* Base-NBASE weight of result and remaining exponent */
                              11177         [ +  + ]:            114 :     if (exp >= 0)
                              11178                 :             81 :         result->weight = exp / DEC_DIGITS;
                              11179                 :                :     else
                              11180                 :             33 :         result->weight = (exp + 1) / DEC_DIGITS - 1;
                              11181                 :                : 
                              11182                 :            114 :     exp -= result->weight * DEC_DIGITS;
                              11183                 :                : 
                              11184                 :                :     /* Final adjustment of the result's single NBASE digit */
                              11185         [ +  + ]:            297 :     while (exp-- > 0)
                              11186                 :            183 :         result->digits[0] *= 10;
                              11187                 :            114 : }
                              11188                 :                : 
                              11189                 :                : /*
                              11190                 :                :  * random_var() - return a random value in the range [rmin, rmax].
                              11191                 :                :  */
                              11192                 :                : static void
  528                         11193                 :          16719 : random_var(pg_prng_state *state, const NumericVar *rmin,
                              11194                 :                :            const NumericVar *rmax, NumericVar *result)
                              11195                 :                : {
                              11196                 :                :     int         rscale;
                              11197                 :                :     NumericVar  rlen;
                              11198                 :                :     int         res_ndigits;
                              11199                 :                :     int         n;
                              11200                 :                :     int         pow10;
                              11201                 :                :     int         i;
                              11202                 :                :     uint64      rlen64;
                              11203                 :                :     int         rlen64_ndigits;
                              11204                 :                : 
                              11205                 :          16719 :     rscale = Max(rmin->dscale, rmax->dscale);
                              11206                 :                : 
                              11207                 :                :     /* Compute rlen = rmax - rmin and check the range bounds */
                              11208                 :          16719 :     init_var(&rlen);
                              11209                 :          16719 :     sub_var(rmax, rmin, &rlen);
                              11210                 :                : 
                              11211         [ +  + ]:          16719 :     if (rlen.sign == NUMERIC_NEG)
                              11212         [ +  - ]:              3 :         ereport(ERROR,
                              11213                 :                :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                              11214                 :                :                 errmsg("lower bound must be less than or equal to upper bound"));
                              11215                 :                : 
                              11216                 :                :     /* Special case for an empty range */
                              11217         [ +  + ]:          16716 :     if (rlen.ndigits == 0)
                              11218                 :                :     {
                              11219                 :              6 :         set_var_from_var(rmin, result);
                              11220                 :              6 :         result->dscale = rscale;
                              11221                 :              6 :         free_var(&rlen);
                              11222                 :              6 :         return;
                              11223                 :                :     }
                              11224                 :                : 
                              11225                 :                :     /*
                              11226                 :                :      * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
                              11227                 :                :      * and shift it to the required range by adding rmin.
                              11228                 :                :      */
                              11229                 :                : 
                              11230                 :                :     /* Required result digits */
                              11231                 :          16710 :     res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
                              11232                 :                : 
                              11233                 :                :     /*
                              11234                 :                :      * To get the required rscale, the final result digit must be a multiple
                              11235                 :                :      * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
                              11236                 :                :      */
                              11237                 :          16710 :     n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
                              11238                 :          16710 :     pow10 = 1;
                              11239         [ +  + ]:          43950 :     for (i = 0; i < n; i++)
                              11240                 :          27240 :         pow10 *= 10;
                              11241                 :                : 
                              11242                 :                :     /*
                              11243                 :                :      * To choose a random value uniformly from the range [0, rlen], we choose
                              11244                 :                :      * from the slightly larger range [0, rlen2], where rlen2 is formed from
                              11245                 :                :      * rlen by copying the first 4 NBASE digits, and setting all remaining
                              11246                 :                :      * decimal digits to "9".
                              11247                 :                :      *
                              11248                 :                :      * Without loss of generality, we can ignore the weight of rlen2 and treat
                              11249                 :                :      * it as a pure integer for the purposes of this discussion.  The process
                              11250                 :                :      * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
                              11251                 :                :      * is a 64-bit integer formed from the first 4 NBASE digits copied from
                              11252                 :                :      * rlen.  Since this trivially factors into smaller pieces that fit in
                              11253                 :                :      * 64-bit integers, the task of choosing a random value uniformly from the
                              11254                 :                :      * rlen2 + 1 possible values in [0, rlen2] is much simpler.
                              11255                 :                :      *
                              11256                 :                :      * If the random value selected is too large, it is rejected, and we try
                              11257                 :                :      * again until we get a result <= rlen, ensuring that the overall result
                              11258                 :                :      * is uniform (no particular value is any more likely than any other).
                              11259                 :                :      *
                              11260                 :                :      * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
                              11261                 :                :      * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
                              11262                 :                :      * when DEC_DIGITS is 4). Therefore the probability of needing to reject
                              11263                 :                :      * the value chosen and retry is less than 1e-13.
                              11264                 :                :      */
                              11265                 :          16710 :     rlen64 = (uint64) rlen.digits[0];
                              11266                 :          16710 :     rlen64_ndigits = 1;
                              11267   [ +  +  +  + ]:          38106 :     while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
                              11268                 :                :     {
                              11269                 :          21396 :         rlen64 *= NBASE;
                              11270         [ +  + ]:          21396 :         if (rlen64_ndigits < rlen.ndigits)
                              11271                 :           3306 :             rlen64 += rlen.digits[rlen64_ndigits];
                              11272                 :          21396 :         rlen64_ndigits++;
                              11273                 :                :     }
                              11274                 :                : 
                              11275                 :                :     /* Loop until we get a result <= rlen */
                              11276                 :                :     do
                              11277                 :                :     {
                              11278                 :                :         NumericDigit *res_digits;
                              11279                 :                :         uint64      rand;
                              11280                 :                :         int         whole_ndigits;
                              11281                 :                : 
                              11282                 :          16710 :         alloc_var(result, res_ndigits);
                              11283                 :          16710 :         result->sign = NUMERIC_POS;
                              11284                 :          16710 :         result->weight = rlen.weight;
                              11285                 :          16710 :         result->dscale = rscale;
                              11286                 :          16710 :         res_digits = result->digits;
                              11287                 :                : 
                              11288                 :                :         /*
                              11289                 :                :          * Set the first rlen64_ndigits using a random value in [0, rlen64].
                              11290                 :                :          *
                              11291                 :                :          * If this is the whole result, and rscale is not a multiple of
                              11292                 :                :          * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
                              11293                 :                :          * multiple of pow10.
                              11294                 :                :          */
                              11295   [ +  +  +  + ]:          16710 :         if (rlen64_ndigits == res_ndigits && pow10 != 1)
                              11296                 :          10566 :             rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
                              11297                 :                :         else
                              11298                 :           6144 :             rand = pg_prng_uint64_range(state, 0, rlen64);
                              11299                 :                : 
                              11300         [ +  + ]:          54816 :         for (i = rlen64_ndigits - 1; i >= 0; i--)
                              11301                 :                :         {
                              11302                 :          38106 :             res_digits[i] = (NumericDigit) (rand % NBASE);
                              11303                 :          38106 :             rand = rand / NBASE;
                              11304                 :                :         }
                              11305                 :                : 
                              11306                 :                :         /*
                              11307                 :                :          * Set the remaining digits to random values in range [0, NBASE),
                              11308                 :                :          * noting that the last digit needs to be a multiple of pow10.
                              11309                 :                :          */
                              11310                 :          16710 :         whole_ndigits = res_ndigits;
                              11311         [ +  + ]:          16710 :         if (pow10 != 1)
                              11312                 :          16605 :             whole_ndigits--;
                              11313                 :                : 
                              11314                 :                :         /* Set whole digits in groups of 4 for best performance */
                              11315                 :          16710 :         i = rlen64_ndigits;
                              11316         [ +  + ]:          16740 :         while (i < whole_ndigits - 3)
                              11317                 :                :         {
                              11318                 :             30 :             rand = pg_prng_uint64_range(state, 0,
                              11319                 :                :                                         (uint64) NBASE * NBASE * NBASE * NBASE - 1);
                              11320                 :             30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
                              11321                 :             30 :             rand = rand / NBASE;
                              11322                 :             30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
                              11323                 :             30 :             rand = rand / NBASE;
                              11324                 :             30 :             res_digits[i++] = (NumericDigit) (rand % NBASE);
                              11325                 :             30 :             rand = rand / NBASE;
                              11326                 :             30 :             res_digits[i++] = (NumericDigit) rand;
                              11327                 :                :         }
                              11328                 :                : 
                              11329                 :                :         /* Remaining whole digits */
                              11330         [ +  + ]:          16815 :         while (i < whole_ndigits)
                              11331                 :                :         {
                              11332                 :            105 :             rand = pg_prng_uint64_range(state, 0, NBASE - 1);
                              11333                 :            105 :             res_digits[i++] = (NumericDigit) rand;
                              11334                 :                :         }
                              11335                 :                : 
                              11336                 :                :         /* Final partial digit (multiple of pow10) */
                              11337         [ +  + ]:          16710 :         if (i < res_ndigits)
                              11338                 :                :         {
                              11339                 :           6039 :             rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
                              11340                 :           6039 :             res_digits[i] = (NumericDigit) rand;
                              11341                 :                :         }
                              11342                 :                : 
                              11343                 :                :         /* Remove leading/trailing zeroes */
                              11344                 :          16710 :         strip_var(result);
                              11345                 :                : 
                              11346                 :                :         /* If result > rlen, try again */
                              11347                 :                : 
                              11348         [ -  + ]:          16710 :     } while (cmp_var(result, &rlen) > 0);
                              11349                 :                : 
                              11350                 :                :     /* Offset the result to the required range */
                              11351                 :          16710 :     add_var(result, rmin, result);
                              11352                 :                : 
                              11353                 :          16710 :     free_var(&rlen);
                              11354                 :                : }
                              11355                 :                : 
                              11356                 :                : 
                              11357                 :                : /* ----------------------------------------------------------------------
                              11358                 :                :  *
                              11359                 :                :  * Following are the lowest level functions that operate unsigned
                              11360                 :                :  * on the variable level
                              11361                 :                :  *
                              11362                 :                :  * ----------------------------------------------------------------------
                              11363                 :                :  */
                              11364                 :                : 
                              11365                 :                : 
                              11366                 :                : /* ----------
                              11367                 :                :  * cmp_abs() -
                              11368                 :                :  *
                              11369                 :                :  *  Compare the absolute values of var1 and var2
                              11370                 :                :  *  Returns:    -1 for ABS(var1) < ABS(var2)
                              11371                 :                :  *              0  for ABS(var1) == ABS(var2)
                              11372                 :                :  *              1  for ABS(var1) > ABS(var2)
                              11373                 :                :  * ----------
                              11374                 :                :  */
                              11375                 :                : static int
 2918 andres@anarazel.de      11376                 :         354663 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
                              11377                 :                : {
 7151 bruce@momjian.us        11378                 :         709326 :     return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
                              11379                 :         354663 :                           var2->digits, var2->ndigits, var2->weight);
                              11380                 :                : }
                              11381                 :                : 
                              11382                 :                : /* ----------
                              11383                 :                :  * cmp_abs_common() -
                              11384                 :                :  *
                              11385                 :                :  *  Main routine of cmp_abs(). This function can be used by both
                              11386                 :                :  *  NumericVar and Numeric.
                              11387                 :                :  * ----------
                              11388                 :                :  */
                              11389                 :                : static int
                              11390                 :       10001364 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
                              11391                 :                :                const NumericDigit *var2digits, int var2ndigits, int var2weight)
                              11392                 :                : {
 9601                         11393                 :       10001364 :     int         i1 = 0;
                              11394                 :       10001364 :     int         i2 = 0;
                              11395                 :                : 
                              11396                 :                :     /* Check any digits before the first common digit */
                              11397                 :                : 
 7151                         11398   [ +  +  +  + ]:       10001364 :     while (var1weight > var2weight && i1 < var1ndigits)
                              11399                 :                :     {
 8205 tgl@sss.pgh.pa.us       11400         [ +  - ]:          13504 :         if (var1digits[i1++] != 0)
 9601 bruce@momjian.us        11401                 :          13504 :             return 1;
 7151 bruce@momjian.us        11402                 :UBC           0 :         var1weight--;
                              11403                 :                :     }
 7151 bruce@momjian.us        11404   [ +  +  +  + ]:CBC     9987860 :     while (var2weight > var1weight && i2 < var2ndigits)
                              11405                 :                :     {
 8205 tgl@sss.pgh.pa.us       11406         [ +  - ]:          76193 :         if (var2digits[i2++] != 0)
 9601 bruce@momjian.us        11407                 :          76193 :             return -1;
 7151 bruce@momjian.us        11408                 :UBC           0 :         var2weight--;
                              11409                 :                :     }
                              11410                 :                : 
                              11411                 :                :     /* At this point, either w1 == w2 or we've run out of digits */
                              11412                 :                : 
 7151 bruce@momjian.us        11413         [ +  + ]:CBC     9911667 :     if (var1weight == var2weight)
                              11414                 :                :     {
                              11415   [ +  +  +  + ]:       16140208 :         while (i1 < var1ndigits && i2 < var2ndigits)
                              11416                 :                :         {
 8205 tgl@sss.pgh.pa.us       11417                 :       10699129 :             int         stat = var1digits[i1++] - var2digits[i2++];
                              11418                 :                : 
 9742 JanWieck@Yahoo.com      11419         [ +  + ]:       10699129 :             if (stat)
                              11420                 :                :             {
                              11421         [ +  + ]:        4467416 :                 if (stat > 0)
                              11422                 :        2667667 :                     return 1;
                              11423                 :        1799749 :                 return -1;
                              11424                 :                :             }
                              11425                 :                :         }
                              11426                 :                :     }
                              11427                 :                : 
                              11428                 :                :     /*
                              11429                 :                :      * At this point, we've run out of digits on one side or the other; so any
                              11430                 :                :      * remaining nonzero digits imply that side is larger
                              11431                 :                :      */
 7151 bruce@momjian.us        11432         [ +  + ]:        5444419 :     while (i1 < var1ndigits)
                              11433                 :                :     {
 8205 tgl@sss.pgh.pa.us       11434         [ +  + ]:           4757 :         if (var1digits[i1++] != 0)
 9747 JanWieck@Yahoo.com      11435                 :           4589 :             return 1;
                              11436                 :                :     }
 7151 bruce@momjian.us        11437         [ +  + ]:        5439824 :     while (i2 < var2ndigits)
                              11438                 :                :     {
 8205 tgl@sss.pgh.pa.us       11439         [ +  + ]:            618 :         if (var2digits[i2++] != 0)
 9747 JanWieck@Yahoo.com      11440                 :            456 :             return -1;
                              11441                 :                :     }
                              11442                 :                : 
                              11443                 :        5439206 :     return 0;
                              11444                 :                : }
                              11445                 :                : 
                              11446                 :                : 
                              11447                 :                : /*
                              11448                 :                :  * add_abs() -
                              11449                 :                :  *
                              11450                 :                :  *  Add the absolute values of two variables into result.
                              11451                 :                :  *  result might point to one of the operands without danger.
                              11452                 :                :  */
                              11453                 :                : static void
 2918 andres@anarazel.de      11454                 :         223069 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                              11455                 :                : {
                              11456                 :                :     NumericDigit *res_buf;
                              11457                 :                :     NumericDigit *res_digits;
                              11458                 :                :     int         res_ndigits;
                              11459                 :                :     int         res_weight;
                              11460                 :                :     int         res_rscale,
                              11461                 :                :                 rscale1,
                              11462                 :                :                 rscale2;
                              11463                 :                :     int         res_dscale;
                              11464                 :                :     int         i,
                              11465                 :                :                 i1,
                              11466                 :                :                 i2;
 9601 bruce@momjian.us        11467                 :         223069 :     int         carry = 0;
                              11468                 :                : 
                              11469                 :                :     /* copy these values into local vars for speed in inner loop */
 9182 tgl@sss.pgh.pa.us       11470                 :         223069 :     int         var1ndigits = var1->ndigits;
                              11471                 :         223069 :     int         var2ndigits = var2->ndigits;
                              11472                 :         223069 :     NumericDigit *var1digits = var1->digits;
                              11473                 :         223069 :     NumericDigit *var2digits = var2->digits;
                              11474                 :                : 
 8601 bruce@momjian.us        11475                 :         223069 :     res_weight = Max(var1->weight, var2->weight) + 1;
                              11476                 :                : 
                              11477                 :         223069 :     res_dscale = Max(var1->dscale, var2->dscale);
                              11478                 :                : 
                              11479                 :                :     /* Note: here we are figuring rscale in base-NBASE digits */
 8205 tgl@sss.pgh.pa.us       11480                 :         223069 :     rscale1 = var1->ndigits - var1->weight - 1;
                              11481                 :         223069 :     rscale2 = var2->ndigits - var2->weight - 1;
                              11482                 :         223069 :     res_rscale = Max(rscale1, rscale2);
                              11483                 :                : 
 9747 JanWieck@Yahoo.com      11484                 :         223069 :     res_ndigits = res_rscale + res_weight + 1;
 9363 tgl@sss.pgh.pa.us       11485         [ -  + ]:         223069 :     if (res_ndigits <= 0)
 9363 tgl@sss.pgh.pa.us       11486                 :UBC           0 :         res_ndigits = 1;
                              11487                 :                : 
 8205 tgl@sss.pgh.pa.us       11488                 :CBC      223069 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                              11489                 :         223069 :     res_buf[0] = 0;             /* spare digit for later rounding */
                              11490                 :         223069 :     res_digits = res_buf + 1;
                              11491                 :                : 
 9747 JanWieck@Yahoo.com      11492                 :         223069 :     i1 = res_rscale + var1->weight + 1;
                              11493                 :         223069 :     i2 = res_rscale + var2->weight + 1;
                              11494         [ +  + ]:        1819205 :     for (i = res_ndigits - 1; i >= 0; i--)
                              11495                 :                :     {
                              11496                 :        1596136 :         i1--;
                              11497                 :        1596136 :         i2--;
 9182 tgl@sss.pgh.pa.us       11498   [ +  +  +  + ]:        1596136 :         if (i1 >= 0 && i1 < var1ndigits)
                              11499                 :         708281 :             carry += var1digits[i1];
                              11500   [ +  +  +  + ]:        1596136 :         if (i2 >= 0 && i2 < var2ndigits)
                              11501                 :         568038 :             carry += var2digits[i2];
                              11502                 :                : 
 8205                         11503         [ +  + ]:        1596136 :         if (carry >= NBASE)
                              11504                 :                :         {
                              11505                 :         112951 :             res_digits[i] = carry - NBASE;
 9182                         11506                 :         112951 :             carry = 1;
                              11507                 :                :         }
                              11508                 :                :         else
                              11509                 :                :         {
                              11510                 :        1483185 :             res_digits[i] = carry;
                              11511                 :        1483185 :             carry = 0;
                              11512                 :                :         }
                              11513                 :                :     }
                              11514                 :                : 
                              11515         [ -  + ]:         223069 :     Assert(carry == 0);         /* else we failed to allow for carry out */
                              11516                 :                : 
 9747 JanWieck@Yahoo.com      11517         [ +  + ]:         223069 :     digitbuf_free(result->buf);
                              11518                 :         223069 :     result->ndigits = res_ndigits;
 9601 bruce@momjian.us        11519                 :         223069 :     result->buf = res_buf;
                              11520                 :         223069 :     result->digits = res_digits;
                              11521                 :         223069 :     result->weight = res_weight;
                              11522                 :         223069 :     result->dscale = res_dscale;
                              11523                 :                : 
                              11524                 :                :     /* Remove leading/trailing zeroes */
 8205 tgl@sss.pgh.pa.us       11525                 :         223069 :     strip_var(result);
 9747 JanWieck@Yahoo.com      11526                 :         223069 : }
                              11527                 :                : 
                              11528                 :                : 
                              11529                 :                : /*
                              11530                 :                :  * sub_abs()
                              11531                 :                :  *
                              11532                 :                :  *  Subtract the absolute value of var2 from the absolute value of var1
                              11533                 :                :  *  and store in result. result might point to one of the operands
                              11534                 :                :  *  without danger.
                              11535                 :                :  *
                              11536                 :                :  *  ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
                              11537                 :                :  */
                              11538                 :                : static void
 2918 andres@anarazel.de      11539                 :         327610 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
                              11540                 :                : {
                              11541                 :                :     NumericDigit *res_buf;
                              11542                 :                :     NumericDigit *res_digits;
                              11543                 :                :     int         res_ndigits;
                              11544                 :                :     int         res_weight;
                              11545                 :                :     int         res_rscale,
                              11546                 :                :                 rscale1,
                              11547                 :                :                 rscale2;
                              11548                 :                :     int         res_dscale;
                              11549                 :                :     int         i,
                              11550                 :                :                 i1,
                              11551                 :                :                 i2;
 9601 bruce@momjian.us        11552                 :         327610 :     int         borrow = 0;
                              11553                 :                : 
                              11554                 :                :     /* copy these values into local vars for speed in inner loop */
 9182 tgl@sss.pgh.pa.us       11555                 :         327610 :     int         var1ndigits = var1->ndigits;
                              11556                 :         327610 :     int         var2ndigits = var2->ndigits;
                              11557                 :         327610 :     NumericDigit *var1digits = var1->digits;
                              11558                 :         327610 :     NumericDigit *var2digits = var2->digits;
                              11559                 :                : 
 9747 JanWieck@Yahoo.com      11560                 :         327610 :     res_weight = var1->weight;
                              11561                 :                : 
 8601 bruce@momjian.us        11562                 :         327610 :     res_dscale = Max(var1->dscale, var2->dscale);
                              11563                 :                : 
                              11564                 :                :     /* Note: here we are figuring rscale in base-NBASE digits */
 8205 tgl@sss.pgh.pa.us       11565                 :         327610 :     rscale1 = var1->ndigits - var1->weight - 1;
                              11566                 :         327610 :     rscale2 = var2->ndigits - var2->weight - 1;
                              11567                 :         327610 :     res_rscale = Max(rscale1, rscale2);
                              11568                 :                : 
 9747 JanWieck@Yahoo.com      11569                 :         327610 :     res_ndigits = res_rscale + res_weight + 1;
 9363 tgl@sss.pgh.pa.us       11570         [ -  + ]:         327610 :     if (res_ndigits <= 0)
 9363 tgl@sss.pgh.pa.us       11571                 :UBC           0 :         res_ndigits = 1;
                              11572                 :                : 
 8205 tgl@sss.pgh.pa.us       11573                 :CBC      327610 :     res_buf = digitbuf_alloc(res_ndigits + 1);
                              11574                 :         327610 :     res_buf[0] = 0;             /* spare digit for later rounding */
                              11575                 :         327610 :     res_digits = res_buf + 1;
                              11576                 :                : 
 9747 JanWieck@Yahoo.com      11577                 :         327610 :     i1 = res_rscale + var1->weight + 1;
                              11578                 :         327610 :     i2 = res_rscale + var2->weight + 1;
                              11579         [ +  + ]:        2594196 :     for (i = res_ndigits - 1; i >= 0; i--)
                              11580                 :                :     {
                              11581                 :        2266586 :         i1--;
                              11582                 :        2266586 :         i2--;
 9182 tgl@sss.pgh.pa.us       11583   [ +  -  +  + ]:        2266586 :         if (i1 >= 0 && i1 < var1ndigits)
                              11584                 :        2053925 :             borrow += var1digits[i1];
                              11585   [ +  +  +  + ]:        2266586 :         if (i2 >= 0 && i2 < var2ndigits)
                              11586                 :        2018016 :             borrow -= var2digits[i2];
                              11587                 :                : 
 9747 JanWieck@Yahoo.com      11588         [ +  + ]:        2266586 :         if (borrow < 0)
                              11589                 :                :         {
 8205 tgl@sss.pgh.pa.us       11590                 :         229158 :             res_digits[i] = borrow + NBASE;
 9747 JanWieck@Yahoo.com      11591                 :         229158 :             borrow = -1;
                              11592                 :                :         }
                              11593                 :                :         else
                              11594                 :                :         {
                              11595                 :        2037428 :             res_digits[i] = borrow;
                              11596                 :        2037428 :             borrow = 0;
                              11597                 :                :         }
                              11598                 :                :     }
                              11599                 :                : 
 9182 tgl@sss.pgh.pa.us       11600         [ -  + ]:         327610 :     Assert(borrow == 0);        /* else caller gave us var1 < var2 */
                              11601                 :                : 
 9747 JanWieck@Yahoo.com      11602         [ +  + ]:         327610 :     digitbuf_free(result->buf);
                              11603                 :         327610 :     result->ndigits = res_ndigits;
 9601 bruce@momjian.us        11604                 :         327610 :     result->buf = res_buf;
                              11605                 :         327610 :     result->digits = res_digits;
                              11606                 :         327610 :     result->weight = res_weight;
                              11607                 :         327610 :     result->dscale = res_dscale;
                              11608                 :                : 
                              11609                 :                :     /* Remove leading/trailing zeroes */
 8205 tgl@sss.pgh.pa.us       11610                 :         327610 :     strip_var(result);
                              11611                 :         327610 : }
                              11612                 :                : 
                              11613                 :                : /*
                              11614                 :                :  * round_var
                              11615                 :                :  *
                              11616                 :                :  * Round the value of a variable to no more than rscale decimal digits
                              11617                 :                :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
                              11618                 :                :  * rounding before the decimal point.
                              11619                 :                :  */
                              11620                 :                : static void
                              11621                 :         124345 : round_var(NumericVar *var, int rscale)
                              11622                 :                : {
 8069 bruce@momjian.us        11623                 :         124345 :     NumericDigit *digits = var->digits;
                              11624                 :                :     int         di;
                              11625                 :                :     int         ndigits;
                              11626                 :                :     int         carry;
                              11627                 :                : 
 8205 tgl@sss.pgh.pa.us       11628                 :         124345 :     var->dscale = rscale;
                              11629                 :                : 
                              11630                 :                :     /* decimal digits wanted */
                              11631                 :         124345 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
                              11632                 :                : 
                              11633                 :                :     /*
                              11634                 :                :      * If di = 0, the value loses all digits, but could round up to 1 if its
                              11635                 :                :      * first extra digit is >= 5.  If di < 0 the result must be 0.
                              11636                 :                :      */
                              11637         [ +  + ]:         124345 :     if (di < 0)
                              11638                 :                :     {
                              11639                 :             52 :         var->ndigits = 0;
                              11640                 :             52 :         var->weight = 0;
                              11641                 :             52 :         var->sign = NUMERIC_POS;
                              11642                 :                :     }
                              11643                 :                :     else
                              11644                 :                :     {
                              11645                 :                :         /* NBASE digits wanted */
 8069 bruce@momjian.us        11646                 :         124293 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
                              11647                 :                : 
                              11648                 :                :         /* 0, or number of decimal digits to keep in last NBASE digit */
 8205 tgl@sss.pgh.pa.us       11649                 :         124293 :         di %= DEC_DIGITS;
                              11650                 :                : 
                              11651         [ +  + ]:         124293 :         if (ndigits < var->ndigits ||
                              11652   [ +  +  +  + ]:          22899 :             (ndigits == var->ndigits && di > 0))
                              11653                 :                :         {
                              11654                 :         103128 :             var->ndigits = ndigits;
                              11655                 :                : 
                              11656                 :                : #if DEC_DIGITS == 1
                              11657                 :                :             /* di must be zero */
                              11658                 :                :             carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
                              11659                 :                : #else
                              11660         [ +  + ]:         103128 :             if (di == 0)
                              11661                 :          82184 :                 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
                              11662                 :                :             else
                              11663                 :                :             {
                              11664                 :                :                 /* Must round within last NBASE digit */
                              11665                 :                :                 int         extra,
                              11666                 :                :                             pow10;
                              11667                 :                : 
                              11668                 :                : #if DEC_DIGITS == 4
                              11669                 :          20944 :                 pow10 = round_powers[di];
                              11670                 :                : #elif DEC_DIGITS == 2
                              11671                 :                :                 pow10 = 10;
                              11672                 :                : #else
                              11673                 :                : #error unsupported NBASE
                              11674                 :                : #endif
                              11675                 :          20944 :                 extra = digits[--ndigits] % pow10;
                              11676                 :          20944 :                 digits[ndigits] -= extra;
                              11677                 :          20944 :                 carry = 0;
 8069 bruce@momjian.us        11678         [ +  + ]:          20944 :                 if (extra >= pow10 / 2)
                              11679                 :                :                 {
 8205 tgl@sss.pgh.pa.us       11680                 :           9724 :                     pow10 += digits[ndigits];
                              11681         [ +  + ]:           9724 :                     if (pow10 >= NBASE)
                              11682                 :                :                     {
                              11683                 :            406 :                         pow10 -= NBASE;
                              11684                 :            406 :                         carry = 1;
                              11685                 :                :                     }
                              11686                 :           9724 :                     digits[ndigits] = pow10;
                              11687                 :                :                 }
                              11688                 :                :             }
                              11689                 :                : #endif
                              11690                 :                : 
                              11691                 :                :             /* Propagate carry if needed */
                              11692         [ +  + ]:         119939 :             while (carry)
                              11693                 :                :             {
                              11694                 :          16811 :                 carry += digits[--ndigits];
                              11695         [ +  + ]:          16811 :                 if (carry >= NBASE)
                              11696                 :                :                 {
                              11697                 :          12313 :                     digits[ndigits] = carry - NBASE;
                              11698                 :          12313 :                     carry = 1;
                              11699                 :                :                 }
                              11700                 :                :                 else
                              11701                 :                :                 {
                              11702                 :           4498 :                     digits[ndigits] = carry;
                              11703                 :           4498 :                     carry = 0;
                              11704                 :                :                 }
                              11705                 :                :             }
                              11706                 :                : 
                              11707         [ +  + ]:         103128 :             if (ndigits < 0)
                              11708                 :                :             {
                              11709         [ -  + ]:             48 :                 Assert(ndigits == -1);  /* better not have added > 1 digit */
                              11710         [ -  + ]:             48 :                 Assert(var->digits > var->buf);
                              11711                 :             48 :                 var->digits--;
                              11712                 :             48 :                 var->ndigits++;
                              11713                 :             48 :                 var->weight++;
                              11714                 :                :             }
                              11715                 :                :         }
                              11716                 :                :     }
                              11717                 :         124345 : }
                              11718                 :                : 
                              11719                 :                : /*
                              11720                 :                :  * trunc_var
                              11721                 :                :  *
                              11722                 :                :  * Truncate (towards zero) the value of a variable at rscale decimal digits
                              11723                 :                :  * after the decimal point.  NOTE: we allow rscale < 0 here, implying
                              11724                 :                :  * truncation before the decimal point.
                              11725                 :                :  */
                              11726                 :                : static void
                              11727                 :         210406 : trunc_var(NumericVar *var, int rscale)
                              11728                 :                : {
                              11729                 :                :     int         di;
                              11730                 :                :     int         ndigits;
                              11731                 :                : 
                              11732                 :         210406 :     var->dscale = rscale;
                              11733                 :                : 
                              11734                 :                :     /* decimal digits wanted */
                              11735                 :         210406 :     di = (var->weight + 1) * DEC_DIGITS + rscale;
                              11736                 :                : 
                              11737                 :                :     /*
                              11738                 :                :      * If di <= 0, the value loses all digits.
                              11739                 :                :      */
                              11740         [ +  + ]:         210406 :     if (di <= 0)
                              11741                 :                :     {
                              11742                 :             45 :         var->ndigits = 0;
                              11743                 :             45 :         var->weight = 0;
                              11744                 :             45 :         var->sign = NUMERIC_POS;
                              11745                 :                :     }
                              11746                 :                :     else
                              11747                 :                :     {
                              11748                 :                :         /* NBASE digits wanted */
 8069 bruce@momjian.us        11749                 :         210361 :         ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
                              11750                 :                : 
 8205 tgl@sss.pgh.pa.us       11751         [ +  + ]:         210361 :         if (ndigits <= var->ndigits)
                              11752                 :                :         {
                              11753                 :         210226 :             var->ndigits = ndigits;
                              11754                 :                : 
                              11755                 :                : #if DEC_DIGITS == 1
                              11756                 :                :             /* no within-digit stuff to worry about */
                              11757                 :                : #else
                              11758                 :                :             /* 0, or number of decimal digits to keep in last NBASE digit */
                              11759                 :         210226 :             di %= DEC_DIGITS;
                              11760                 :                : 
                              11761         [ +  + ]:         210226 :             if (di > 0)
                              11762                 :                :             {
                              11763                 :                :                 /* Must truncate within last NBASE digit */
 8069 bruce@momjian.us        11764                 :             53 :                 NumericDigit *digits = var->digits;
                              11765                 :                :                 int         extra,
                              11766                 :                :                             pow10;
                              11767                 :                : 
                              11768                 :                : #if DEC_DIGITS == 4
 8205 tgl@sss.pgh.pa.us       11769                 :             53 :                 pow10 = round_powers[di];
                              11770                 :                : #elif DEC_DIGITS == 2
                              11771                 :                :                 pow10 = 10;
                              11772                 :                : #else
                              11773                 :                : #error unsupported NBASE
                              11774                 :                : #endif
                              11775                 :             53 :                 extra = digits[--ndigits] % pow10;
                              11776                 :             53 :                 digits[ndigits] -= extra;
                              11777                 :                :             }
                              11778                 :                : #endif
                              11779                 :                :         }
                              11780                 :                :     }
                              11781                 :         210406 : }
                              11782                 :                : 
                              11783                 :                : /*
                              11784                 :                :  * strip_var
                              11785                 :                :  *
                              11786                 :                :  * Strip any leading and trailing zeroes from a numeric variable
                              11787                 :                :  */
                              11788                 :                : static void
                              11789                 :        1642443 : strip_var(NumericVar *var)
                              11790                 :                : {
 8069 bruce@momjian.us        11791                 :        1642443 :     NumericDigit *digits = var->digits;
 8205 tgl@sss.pgh.pa.us       11792                 :        1642443 :     int         ndigits = var->ndigits;
                              11793                 :                : 
                              11794                 :                :     /* Strip leading zeroes */
                              11795   [ +  +  +  + ]:        2815324 :     while (ndigits > 0 && *digits == 0)
                              11796                 :                :     {
                              11797                 :        1172881 :         digits++;
                              11798                 :        1172881 :         var->weight--;
                              11799                 :        1172881 :         ndigits--;
                              11800                 :                :     }
                              11801                 :                : 
                              11802                 :                :     /* Strip trailing zeroes */
                              11803   [ +  +  +  + ]:        1979866 :     while (ndigits > 0 && digits[ndigits - 1] == 0)
                              11804                 :         337423 :         ndigits--;
                              11805                 :                : 
                              11806                 :                :     /* If it's zero, normalize the sign and weight */
                              11807         [ +  + ]:        1642443 :     if (ndigits == 0)
                              11808                 :                :     {
                              11809                 :          25167 :         var->sign = NUMERIC_POS;
                              11810                 :          25167 :         var->weight = 0;
                              11811                 :                :     }
                              11812                 :                : 
                              11813                 :        1642443 :     var->digits = digits;
                              11814                 :        1642443 :     var->ndigits = ndigits;
 9747 JanWieck@Yahoo.com      11815                 :        1642443 : }
                              11816                 :                : 
                              11817                 :                : 
                              11818                 :                : /* ----------------------------------------------------------------------
                              11819                 :                :  *
                              11820                 :                :  * Fast sum accumulator functions
                              11821                 :                :  *
                              11822                 :                :  * ----------------------------------------------------------------------
                              11823                 :                :  */
                              11824                 :                : 
                              11825                 :                : /*
                              11826                 :                :  * Reset the accumulator's value to zero.  The buffers to hold the digits
                              11827                 :                :  * are not free'd.
                              11828                 :                :  */
                              11829                 :                : static void
 3291 heikki.linnakangas@i    11830                 :              9 : accum_sum_reset(NumericSumAccum *accum)
                              11831                 :                : {
                              11832                 :                :     int         i;
                              11833                 :                : 
                              11834                 :              9 :     accum->dscale = 0;
                              11835         [ +  + ]:             33 :     for (i = 0; i < accum->ndigits; i++)
                              11836                 :                :     {
                              11837                 :             24 :         accum->pos_digits[i] = 0;
                              11838                 :             24 :         accum->neg_digits[i] = 0;
                              11839                 :                :     }
                              11840                 :              9 : }
                              11841                 :                : 
                              11842                 :                : /*
                              11843                 :                :  * Accumulate a new value.
                              11844                 :                :  */
                              11845                 :                : static void
 2918 andres@anarazel.de      11846                 :        1177858 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
                              11847                 :                : {
                              11848                 :                :     int32      *accum_digits;
                              11849                 :                :     int         i,
                              11850                 :                :                 val_i;
                              11851                 :                :     int         val_ndigits;
                              11852                 :                :     NumericDigit *val_digits;
                              11853                 :                : 
                              11854                 :                :     /*
                              11855                 :                :      * If we have accumulated too many values since the last carry
                              11856                 :                :      * propagation, do it now, to avoid overflowing.  (We could allow more
                              11857                 :                :      * than NBASE - 1, if we reserved two extra digits, rather than one, for
                              11858                 :                :      * carry propagation.  But even with NBASE - 1, this needs to be done so
                              11859                 :                :      * seldom, that the performance difference is negligible.)
                              11860                 :                :      */
 3291 heikki.linnakangas@i    11861         [ +  + ]:        1177858 :     if (accum->num_uncarried == NBASE - 1)
                              11862                 :             72 :         accum_sum_carry(accum);
                              11863                 :                : 
                              11864                 :                :     /*
                              11865                 :                :      * Adjust the weight or scale of the old value, so that it can accommodate
                              11866                 :                :      * the new value.
                              11867                 :                :      */
                              11868                 :        1177858 :     accum_sum_rescale(accum, val);
                              11869                 :                : 
                              11870                 :                :     /* */
                              11871         [ +  + ]:        1177858 :     if (val->sign == NUMERIC_POS)
                              11872                 :         877519 :         accum_digits = accum->pos_digits;
                              11873                 :                :     else
                              11874                 :         300339 :         accum_digits = accum->neg_digits;
                              11875                 :                : 
                              11876                 :                :     /* copy these values into local vars for speed in loop */
                              11877                 :        1177858 :     val_ndigits = val->ndigits;
                              11878                 :        1177858 :     val_digits = val->digits;
                              11879                 :                : 
                              11880                 :        1177858 :     i = accum->weight - val->weight;
                              11881         [ +  + ]:        5944987 :     for (val_i = 0; val_i < val_ndigits; val_i++)
                              11882                 :                :     {
                              11883                 :        4767129 :         accum_digits[i] += (int32) val_digits[val_i];
                              11884                 :        4767129 :         i++;
                              11885                 :                :     }
                              11886                 :                : 
                              11887                 :        1177858 :     accum->num_uncarried++;
                              11888                 :        1177858 : }
                              11889                 :                : 
                              11890                 :                : /*
                              11891                 :                :  * Propagate carries.
                              11892                 :                :  */
                              11893                 :                : static void
                              11894                 :          86379 : accum_sum_carry(NumericSumAccum *accum)
                              11895                 :                : {
                              11896                 :                :     int         i;
                              11897                 :                :     int         ndigits;
                              11898                 :                :     int32      *dig;
                              11899                 :                :     int32       carry;
                              11900                 :          86379 :     int32       newdig = 0;
                              11901                 :                : 
                              11902                 :                :     /*
                              11903                 :                :      * If no new values have been added since last carry propagation, nothing
                              11904                 :                :      * to do.
                              11905                 :                :      */
                              11906         [ +  + ]:          86379 :     if (accum->num_uncarried == 0)
                              11907                 :             36 :         return;
                              11908                 :                : 
                              11909                 :                :     /*
                              11910                 :                :      * We maintain that the weight of the accumulator is always one larger
                              11911                 :                :      * than needed to hold the current value, before carrying, to make sure
                              11912                 :                :      * there is enough space for the possible extra digit when carry is
                              11913                 :                :      * propagated.  We cannot expand the buffer here, unless we require
                              11914                 :                :      * callers of accum_sum_final() to switch to the right memory context.
                              11915                 :                :      */
                              11916   [ +  -  -  + ]:          86343 :     Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
                              11917                 :                : 
                              11918                 :          86343 :     ndigits = accum->ndigits;
                              11919                 :                : 
                              11920                 :                :     /* Propagate carry in the positive sum */
                              11921                 :          86343 :     dig = accum->pos_digits;
                              11922                 :          86343 :     carry = 0;
                              11923         [ +  + ]:        1302759 :     for (i = ndigits - 1; i >= 0; i--)
                              11924                 :                :     {
                              11925                 :        1216416 :         newdig = dig[i] + carry;
                              11926         [ +  + ]:        1216416 :         if (newdig >= NBASE)
                              11927                 :                :         {
                              11928                 :          55399 :             carry = newdig / NBASE;
                              11929                 :          55399 :             newdig -= carry * NBASE;
                              11930                 :                :         }
                              11931                 :                :         else
                              11932                 :        1161017 :             carry = 0;
                              11933                 :        1216416 :         dig[i] = newdig;
                              11934                 :                :     }
                              11935                 :                :     /* Did we use up the digit reserved for carry propagation? */
                              11936         [ +  + ]:          86343 :     if (newdig > 0)
                              11937                 :           1320 :         accum->have_carry_space = false;
                              11938                 :                : 
                              11939                 :                :     /* And the same for the negative sum */
                              11940                 :          86343 :     dig = accum->neg_digits;
                              11941                 :          86343 :     carry = 0;
                              11942         [ +  + ]:        1302759 :     for (i = ndigits - 1; i >= 0; i--)
                              11943                 :                :     {
                              11944                 :        1216416 :         newdig = dig[i] + carry;
                              11945         [ +  + ]:        1216416 :         if (newdig >= NBASE)
                              11946                 :                :         {
                              11947                 :             99 :             carry = newdig / NBASE;
                              11948                 :             99 :             newdig -= carry * NBASE;
                              11949                 :                :         }
                              11950                 :                :         else
                              11951                 :        1216317 :             carry = 0;
                              11952                 :        1216416 :         dig[i] = newdig;
                              11953                 :                :     }
                              11954         [ +  + ]:          86343 :     if (newdig > 0)
                              11955                 :             15 :         accum->have_carry_space = false;
                              11956                 :                : 
                              11957                 :          86343 :     accum->num_uncarried = 0;
                              11958                 :                : }
                              11959                 :                : 
                              11960                 :                : /*
                              11961                 :                :  * Re-scale accumulator to accommodate new value.
                              11962                 :                :  *
                              11963                 :                :  * If the new value has more digits than the current digit buffers in the
                              11964                 :                :  * accumulator, enlarge the buffers.
                              11965                 :                :  */
                              11966                 :                : static void
 2918 andres@anarazel.de      11967                 :        1177858 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
                              11968                 :                : {
 3291 heikki.linnakangas@i    11969                 :        1177858 :     int         old_weight = accum->weight;
                              11970                 :        1177858 :     int         old_ndigits = accum->ndigits;
                              11971                 :                :     int         accum_ndigits;
                              11972                 :                :     int         accum_weight;
                              11973                 :                :     int         accum_rscale;
                              11974                 :                :     int         val_rscale;
                              11975                 :                : 
                              11976                 :        1177858 :     accum_weight = old_weight;
                              11977                 :        1177858 :     accum_ndigits = old_ndigits;
                              11978                 :                : 
                              11979                 :                :     /*
                              11980                 :                :      * Does the new value have a larger weight? If so, enlarge the buffers,
                              11981                 :                :      * and shift the existing value to the new weight, by adding leading
                              11982                 :                :      * zeros.
                              11983                 :                :      *
                              11984                 :                :      * We enforce that the accumulator always has a weight one larger than
                              11985                 :                :      * needed for the inputs, so that we have space for an extra digit at the
                              11986                 :                :      * final carry-propagation phase, if necessary.
                              11987                 :                :      */
                              11988         [ +  + ]:        1177858 :     if (val->weight >= accum_weight)
                              11989                 :                :     {
                              11990                 :         131118 :         accum_weight = val->weight + 1;
                              11991                 :         131118 :         accum_ndigits = accum_ndigits + (accum_weight - old_weight);
                              11992                 :                :     }
                              11993                 :                : 
                              11994                 :                :     /*
                              11995                 :                :      * Even though the new value is small, we might've used up the space
                              11996                 :                :      * reserved for the carry digit in the last call to accum_sum_carry().  If
                              11997                 :                :      * so, enlarge to make room for another one.
                              11998                 :                :      */
                              11999         [ +  + ]:        1046740 :     else if (!accum->have_carry_space)
                              12000                 :                :     {
                              12001                 :             36 :         accum_weight++;
                              12002                 :             36 :         accum_ndigits++;
                              12003                 :                :     }
                              12004                 :                : 
                              12005                 :                :     /* Is the new value wider on the right side? */
                              12006                 :        1177858 :     accum_rscale = accum_ndigits - accum_weight - 1;
                              12007                 :        1177858 :     val_rscale = val->ndigits - val->weight - 1;
                              12008         [ +  + ]:        1177858 :     if (val_rscale > accum_rscale)
                              12009                 :          86129 :         accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
                              12010                 :                : 
                              12011   [ +  +  -  + ]:        1177858 :     if (accum_ndigits != old_ndigits ||
                              12012                 :                :         accum_weight != old_weight)
                              12013                 :                :     {
                              12014                 :                :         int32      *new_pos_digits;
                              12015                 :                :         int32      *new_neg_digits;
                              12016                 :                :         int         weightdiff;
                              12017                 :                : 
                              12018                 :         131292 :         weightdiff = accum_weight - old_weight;
                              12019                 :                : 
                              12020                 :         131292 :         new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
                              12021                 :         131292 :         new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
                              12022                 :                : 
                              12023         [ +  + ]:         131292 :         if (accum->pos_digits)
                              12024                 :                :         {
                              12025                 :          45198 :             memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
                              12026                 :                :                    old_ndigits * sizeof(int32));
                              12027                 :          45198 :             pfree(accum->pos_digits);
                              12028                 :                : 
                              12029                 :          45198 :             memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
                              12030                 :                :                    old_ndigits * sizeof(int32));
                              12031                 :          45198 :             pfree(accum->neg_digits);
                              12032                 :                :         }
                              12033                 :                : 
                              12034                 :         131292 :         accum->pos_digits = new_pos_digits;
                              12035                 :         131292 :         accum->neg_digits = new_neg_digits;
                              12036                 :                : 
                              12037                 :         131292 :         accum->weight = accum_weight;
                              12038                 :         131292 :         accum->ndigits = accum_ndigits;
                              12039                 :                : 
                              12040   [ +  -  -  + ]:         131292 :         Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
                              12041                 :         131292 :         accum->have_carry_space = true;
                              12042                 :                :     }
                              12043                 :                : 
                              12044         [ +  + ]:        1177858 :     if (val->dscale > accum->dscale)
                              12045                 :            150 :         accum->dscale = val->dscale;
                              12046                 :        1177858 : }
                              12047                 :                : 
                              12048                 :                : /*
                              12049                 :                :  * Return the current value of the accumulator.  This perform final carry
                              12050                 :                :  * propagation, and adds together the positive and negative sums.
                              12051                 :                :  *
                              12052                 :                :  * Unlike all the other routines, the caller is not required to switch to
                              12053                 :                :  * the memory context that holds the accumulator.
                              12054                 :                :  */
                              12055                 :                : static void
                              12056                 :          86307 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
                              12057                 :                : {
                              12058                 :                :     int         i;
                              12059                 :                :     NumericVar  pos_var;
                              12060                 :                :     NumericVar  neg_var;
                              12061                 :                : 
                              12062         [ -  + ]:          86307 :     if (accum->ndigits == 0)
                              12063                 :                :     {
 3291 heikki.linnakangas@i    12064                 :UBC           0 :         set_var_from_var(&const_zero, result);
                              12065                 :              0 :         return;
                              12066                 :                :     }
                              12067                 :                : 
                              12068                 :                :     /* Perform final carry */
 3291 heikki.linnakangas@i    12069                 :CBC       86307 :     accum_sum_carry(accum);
                              12070                 :                : 
                              12071                 :                :     /* Create NumericVars representing the positive and negative sums */
                              12072                 :          86307 :     init_var(&pos_var);
                              12073                 :          86307 :     init_var(&neg_var);
                              12074                 :                : 
                              12075                 :          86307 :     pos_var.ndigits = neg_var.ndigits = accum->ndigits;
                              12076                 :          86307 :     pos_var.weight = neg_var.weight = accum->weight;
                              12077                 :          86307 :     pos_var.dscale = neg_var.dscale = accum->dscale;
                              12078                 :          86307 :     pos_var.sign = NUMERIC_POS;
                              12079                 :          86307 :     neg_var.sign = NUMERIC_NEG;
                              12080                 :                : 
                              12081                 :          86307 :     pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
                              12082                 :          86307 :     neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
                              12083                 :                : 
                              12084         [ +  + ]:        1302563 :     for (i = 0; i < accum->ndigits; i++)
                              12085                 :                :     {
                              12086         [ -  + ]:        1216256 :         Assert(accum->pos_digits[i] < NBASE);
                              12087                 :        1216256 :         pos_var.digits[i] = (int16) accum->pos_digits[i];
                              12088                 :                : 
                              12089         [ -  + ]:        1216256 :         Assert(accum->neg_digits[i] < NBASE);
                              12090                 :        1216256 :         neg_var.digits[i] = (int16) accum->neg_digits[i];
                              12091                 :                :     }
                              12092                 :                : 
                              12093                 :                :     /* And add them together */
                              12094                 :          86307 :     add_var(&pos_var, &neg_var, result);
                              12095                 :                : 
                              12096                 :                :     /* Remove leading/trailing zeroes */
                              12097                 :          86307 :     strip_var(result);
                              12098                 :                : }
                              12099                 :                : 
                              12100                 :                : /*
                              12101                 :                :  * Copy an accumulator's state.
                              12102                 :                :  *
                              12103                 :                :  * 'dst' is assumed to be uninitialized beforehand.  No attempt is made at
                              12104                 :                :  * freeing old values.
                              12105                 :                :  */
                              12106                 :                : static void
                              12107                 :             21 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
                              12108                 :                : {
                              12109                 :             21 :     dst->pos_digits = palloc(src->ndigits * sizeof(int32));
                              12110                 :             21 :     dst->neg_digits = palloc(src->ndigits * sizeof(int32));
                              12111                 :                : 
                              12112                 :             21 :     memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
                              12113                 :             21 :     memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
                              12114                 :             21 :     dst->num_uncarried = src->num_uncarried;
                              12115                 :             21 :     dst->ndigits = src->ndigits;
                              12116                 :             21 :     dst->weight = src->weight;
                              12117                 :             21 :     dst->dscale = src->dscale;
                              12118                 :             21 : }
                              12119                 :                : 
                              12120                 :                : /*
                              12121                 :                :  * Add the current value of 'accum2' into 'accum'.
                              12122                 :                :  */
                              12123                 :                : static void
                              12124                 :             27 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
                              12125                 :                : {
                              12126                 :                :     NumericVar  tmp_var;
                              12127                 :                : 
                              12128                 :             27 :     init_var(&tmp_var);
                              12129                 :                : 
                              12130                 :             27 :     accum_sum_final(accum2, &tmp_var);
                              12131                 :             27 :     accum_sum_add(accum, &tmp_var);
                              12132                 :                : 
                              12133                 :             27 :     free_var(&tmp_var);
                              12134                 :             27 : }
        

Generated by: LCOV version 2.4-beta