PostgreSQL Source Code  git master
numeric.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include "access/hash.h"
#include "catalog/pg_type.h"
#include "common/int.h"
#include "funcapi.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/int8.h"
#include "utils/numeric.h"
#include "utils/sortsupport.h"
Include dependency graph for numeric.c:

Go to the source code of this file.

Data Structures

struct  NumericShort
 
struct  NumericLong
 
union  NumericChoice
 
struct  NumericData
 
struct  NumericVar
 
struct  generate_series_numeric_fctx
 
struct  NumericSortSupport
 
struct  NumericSumAccum
 
struct  NumericAggState
 
struct  Int8TransTypeData
 

Macros

#define NBASE   10000
 
#define HALF_NBASE   5000
 
#define DEC_DIGITS   4 /* decimal digits per NBASE digit */
 
#define MUL_GUARD_DIGITS   2 /* these are measured in NBASE digits */
 
#define DIV_GUARD_DIGITS   4
 
#define NUMERIC_SIGN_MASK   0xC000
 
#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_SHORT   0x8000
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_NAN)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
 
#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))
 
#define NUMERIC_HEADER_IS_SHORT(n)   (((n)->choice.n_header & 0x8000) != 0)
 
#define NUMERIC_HEADER_SIZE(n)
 
#define NUMERIC_SHORT_SIGN_MASK   0x2000
 
#define NUMERIC_SHORT_DSCALE_MASK   0x1F80
 
#define NUMERIC_SHORT_DSCALE_SHIFT   7
 
#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
 
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040
 
#define NUMERIC_SHORT_WEIGHT_MASK   0x003F
 
#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK
 
#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))
 
#define NUMERIC_DSCALE_MASK   0x3FFF
 
#define NUMERIC_SIGN(n)
 
#define NUMERIC_DSCALE(n)
 
#define NUMERIC_WEIGHT(n)
 
#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)
 
#define NumericAbbrevGetDatum(X)   ((Datum) SET_4_BYTES(X))
 
#define DatumGetNumericAbbrev(X)   ((int32) GET_4_BYTES(X))
 
#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)
 
#define dump_numeric(s, n)
 
#define dump_var(s, v)
 
#define digitbuf_alloc(ndigits)   ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
 
#define digitbuf_free(buf)
 
#define init_var(v)   MemSetAligned(v, 0, sizeof(NumericVar))
 
#define NUMERIC_DIGITS(num)
 
#define NUMERIC_NDIGITS(num)   ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
 
#define NUMERIC_CAN_BE_SHORT(scale, weight)
 
#define makePolyNumAggState   makeNumericAggState
 
#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext
 

Typedefs

typedef int16 NumericDigit
 
typedef struct NumericVar NumericVar
 
typedef struct NumericSumAccum NumericSumAccum
 
typedef struct NumericAggState NumericAggState
 
typedef NumericAggState PolyNumAggState
 
typedef struct Int8TransTypeData Int8TransTypeData
 

Functions

static void alloc_var (NumericVar *var, int ndigits)
 
static void free_var (NumericVar *var)
 
static void zero_var (NumericVar *var)
 
static const char * set_var_from_str (const char *str, const char *cp, NumericVar *dest)
 
static void set_var_from_num (Numeric value, NumericVar *dest)
 
static void init_var_from_num (Numeric num, NumericVar *dest)
 
static void set_var_from_var (const NumericVar *value, NumericVar *dest)
 
static char * get_str_from_var (const NumericVar *var)
 
static char * get_str_from_var_sci (const NumericVar *var, int rscale)
 
static Numeric make_result (const NumericVar *var)
 
static void apply_typmod (NumericVar *var, int32 typmod)
 
static int32 numericvar_to_int32 (const NumericVar *var)
 
static bool numericvar_to_int64 (const NumericVar *var, int64 *result)
 
static void int64_to_numericvar (int64 val, NumericVar *var)
 
static double numeric_to_double_no_overflow (Numeric num)
 
static double numericvar_to_double_no_overflow (const NumericVar *var)
 
static Datum numeric_abbrev_convert (Datum original_datum, SortSupport ssup)
 
static bool numeric_abbrev_abort (int memtupcount, SortSupport ssup)
 
static int numeric_fast_cmp (Datum x, Datum y, SortSupport ssup)
 
static int numeric_cmp_abbrev (Datum x, Datum y, SortSupport ssup)
 
static Datum numeric_abbrev_convert_var (const NumericVar *var, NumericSortSupport *nss)
 
static int cmp_numerics (Numeric num1, Numeric num2)
 
static int cmp_var (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_var_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
 
static void add_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void mul_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
 
static void div_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static void div_var_fast (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static int select_div_scale (const NumericVar *var1, const NumericVar *var2)
 
static void mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void ceil_var (const NumericVar *var, NumericVar *result)
 
static void floor_var (const NumericVar *var, NumericVar *result)
 
static void sqrt_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static void exp_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static int estimate_ln_dweight (const NumericVar *var)
 
static void ln_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static void log_var (const NumericVar *base, const NumericVar *num, NumericVar *result)
 
static void power_var (const NumericVar *base, const NumericVar *exp, NumericVar *result)
 
static void power_var_int (const NumericVar *base, int exp, NumericVar *result, int rscale)
 
static int cmp_abs (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_abs_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
 
static void add_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void round_var (NumericVar *var, int rscale)
 
static void trunc_var (NumericVar *var, int rscale)
 
static void strip_var (NumericVar *var)
 
static void compute_bucket (Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
 
static void accum_sum_add (NumericSumAccum *accum, const NumericVar *var1)
 
static void accum_sum_rescale (NumericSumAccum *accum, const NumericVar *val)
 
static void accum_sum_carry (NumericSumAccum *accum)
 
static void accum_sum_reset (NumericSumAccum *accum)
 
static void accum_sum_final (NumericSumAccum *accum, NumericVar *result)
 
static void accum_sum_copy (NumericSumAccum *dst, NumericSumAccum *src)
 
static void accum_sum_combine (NumericSumAccum *accum, NumericSumAccum *accum2)
 
Datum numeric_in (PG_FUNCTION_ARGS)
 
Datum numeric_out (PG_FUNCTION_ARGS)
 
bool numeric_is_nan (Numeric num)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Datum numeric_recv (PG_FUNCTION_ARGS)
 
Datum numeric_send (PG_FUNCTION_ARGS)
 
Datum numeric_transform (PG_FUNCTION_ARGS)
 
Datum numeric (PG_FUNCTION_ARGS)
 
Datum numerictypmodin (PG_FUNCTION_ARGS)
 
Datum numerictypmodout (PG_FUNCTION_ARGS)
 
Datum numeric_abs (PG_FUNCTION_ARGS)
 
Datum numeric_uminus (PG_FUNCTION_ARGS)
 
Datum numeric_uplus (PG_FUNCTION_ARGS)
 
Datum numeric_sign (PG_FUNCTION_ARGS)
 
Datum numeric_round (PG_FUNCTION_ARGS)
 
Datum numeric_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_ceil (PG_FUNCTION_ARGS)
 
Datum numeric_floor (PG_FUNCTION_ARGS)
 
Datum generate_series_numeric (PG_FUNCTION_ARGS)
 
Datum generate_series_step_numeric (PG_FUNCTION_ARGS)
 
Datum width_bucket_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_sortsupport (PG_FUNCTION_ARGS)
 
Datum numeric_cmp (PG_FUNCTION_ARGS)
 
Datum numeric_eq (PG_FUNCTION_ARGS)
 
Datum numeric_ne (PG_FUNCTION_ARGS)
 
Datum numeric_gt (PG_FUNCTION_ARGS)
 
Datum numeric_ge (PG_FUNCTION_ARGS)
 
Datum numeric_lt (PG_FUNCTION_ARGS)
 
Datum numeric_le (PG_FUNCTION_ARGS)
 
Datum hash_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric_extended (PG_FUNCTION_ARGS)
 
Datum numeric_add (PG_FUNCTION_ARGS)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
Datum numeric_inc (PG_FUNCTION_ARGS)
 
Datum numeric_smaller (PG_FUNCTION_ARGS)
 
Datum numeric_larger (PG_FUNCTION_ARGS)
 
Datum numeric_fac (PG_FUNCTION_ARGS)
 
Datum numeric_sqrt (PG_FUNCTION_ARGS)
 
Datum numeric_exp (PG_FUNCTION_ARGS)
 
Datum numeric_ln (PG_FUNCTION_ARGS)
 
Datum numeric_log (PG_FUNCTION_ARGS)
 
Datum numeric_power (PG_FUNCTION_ARGS)
 
Datum numeric_scale (PG_FUNCTION_ARGS)
 
Datum int4_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int4 (PG_FUNCTION_ARGS)
 
Datum int8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int8 (PG_FUNCTION_ARGS)
 
Datum int2_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int2 (PG_FUNCTION_ARGS)
 
Datum float8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float8 (PG_FUNCTION_ARGS)
 
Datum numeric_float8_no_overflow (PG_FUNCTION_ARGS)
 
Datum float4_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float4 (PG_FUNCTION_ARGS)
 
static NumericAggStatemakeNumericAggState (FunctionCallInfo fcinfo, bool calcSumX2)
 
static NumericAggStatemakeNumericAggStateCurrentContext (bool calcSumX2)
 
static void do_numeric_accum (NumericAggState *state, Numeric newval)
 
static bool do_numeric_discard (NumericAggState *state, Numeric newval)
 
Datum numeric_accum (PG_FUNCTION_ARGS)
 
Datum numeric_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_accum (PG_FUNCTION_ARGS)
 
Datum numeric_avg_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_accum_inv (PG_FUNCTION_ARGS)
 
Datum int2_accum (PG_FUNCTION_ARGS)
 
Datum int4_accum (PG_FUNCTION_ARGS)
 
Datum int8_accum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_combine (PG_FUNCTION_ARGS)
 
Datum numeric_poly_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_poly_deserialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum (PG_FUNCTION_ARGS)
 
Datum int8_avg_combine (PG_FUNCTION_ARGS)
 
Datum int8_avg_serialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum int2_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum numeric_poly_sum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_avg (PG_FUNCTION_ARGS)
 
Datum numeric_avg (PG_FUNCTION_ARGS)
 
Datum numeric_sum (PG_FUNCTION_ARGS)
 
static Numeric numeric_stddev_internal (NumericAggState *state, bool variance, bool sample, bool *is_null)
 
Datum numeric_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_pop (PG_FUNCTION_ARGS)
 
Datum int2_sum (PG_FUNCTION_ARGS)
 
Datum int4_sum (PG_FUNCTION_ARGS)
 
Datum int8_sum (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_combine (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg (PG_FUNCTION_ARGS)
 
Datum int2int4_sum (PG_FUNCTION_ARGS)
 

Variables

static const NumericDigit const_zero_data [1] = {0}
 
static const NumericVar const_zero
 
static const NumericDigit const_one_data [1] = {1}
 
static const NumericVar const_one
 
static const NumericDigit const_two_data [1] = {2}
 
static const NumericVar const_two
 
static const NumericDigit const_ten_data [1] = {10}
 
static const NumericVar const_ten
 
static const NumericDigit const_zero_point_five_data [1] = {5000}
 
static const NumericVar const_zero_point_five
 
static const NumericDigit const_zero_point_nine_data [1] = {9000}
 
static const NumericVar const_zero_point_nine
 
static const NumericDigit const_one_point_one_data [2] = {1, 1000}
 
static const NumericVar const_one_point_one
 
static const NumericVar const_nan
 
static const int round_powers [4] = {0, 1000, 100, 10}
 

Macro Definition Documentation

◆ DatumGetNumericAbbrev

#define DatumGetNumericAbbrev (   X)    ((int32) GET_4_BYTES(X))

Definition at line 362 of file numeric.c.

Referenced by numeric_cmp_abbrev().

◆ DEC_DIGITS

◆ digitbuf_alloc

#define digitbuf_alloc (   ndigits)    ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))

Definition at line 444 of file numeric.c.

Referenced by accum_sum_final(), add_abs(), alloc_var(), set_var_from_var(), and sub_abs().

◆ digitbuf_free

#define digitbuf_free (   buf)
Value:
do { \
if ((buf) != NULL) \
pfree(buf); \
} while (0)
static char * buf
Definition: pg_test_fsync.c:67

Definition at line 446 of file numeric.c.

Referenced by add_abs(), alloc_var(), free_var(), set_var_from_var(), sub_abs(), and zero_var().

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 98 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 440 of file numeric.c.

Referenced by int2int4_sum(), and make_result().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 441 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 95 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 4016 of file numeric.c.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ MUL_GUARD_DIGITS

#define MUL_GUARD_DIGITS   2 /* these are measured in NBASE digits */

Definition at line 97 of file numeric.c.

Referenced by mul_var().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 355 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 363 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_CAN_BE_SHORT

#define NUMERIC_CAN_BE_SHORT (   scale,
  weight 
)
Value:
(weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:198
int scale
Definition: pgbench.c:111
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:199
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:194

Definition at line 458 of file numeric.c.

Referenced by make_result(), and numeric().

◆ NUMERIC_DIGITS

#define NUMERIC_DIGITS (   num)
Value:
(num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:182

Definition at line 454 of file numeric.c.

Referenced by cmp_numerics(), hash_numeric(), hash_numeric_extended(), init_var_from_num(), int2int4_sum(), make_result(), and set_var_from_num().

◆ NUMERIC_DSCALE

#define NUMERIC_DSCALE (   n)
Value:
((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
: ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:182
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:205
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:192
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:193

Definition at line 211 of file numeric.c.

Referenced by init_var_from_num(), int2int4_sum(), make_result(), numeric(), numeric_abs(), numeric_scale(), numeric_uminus(), and set_var_from_num().

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 205 of file numeric.c.

Referenced by make_result(), numeric(), and numeric_recv().

◆ NUMERIC_FLAGBITS

#define NUMERIC_FLAGBITS (   n)    ((n)->choice.n_header & NUMERIC_SIGN_MASK)

Definition at line 170 of file numeric.c.

◆ NUMERIC_HDRSZ

#define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))

Definition at line 174 of file numeric.c.

Referenced by make_result(), and numeric_maximum_size().

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 175 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_HEADER_IS_SHORT

#define NUMERIC_HEADER_IS_SHORT (   n)    (((n)->choice.n_header & 0x8000) != 0)

Definition at line 182 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

#define NUMERIC_HEADER_SIZE (   n)
Value:
(VARHDRSZ + sizeof(uint16) + \
(NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
signed short int16
Definition: c.h:293
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:182
#define VARHDRSZ
Definition: c.h:503
unsigned short uint16
Definition: c.h:305

Definition at line 183 of file numeric.c.

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_SHORT

#define NUMERIC_IS_SHORT (   n)    (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)

Definition at line 172 of file numeric.c.

Referenced by numeric(), numeric_abs(), and numeric_uminus().

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

◆ NUMERIC_NDIGITS

#define NUMERIC_NDIGITS (   num)    ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))

◆ NUMERIC_NEG

◆ NUMERIC_POS

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 167 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 192 of file numeric.c.

Referenced by numeric().

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 194 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 193 of file numeric.c.

Referenced by make_result(), and numeric().

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 191 of file numeric.c.

Referenced by make_result(), numeric_abs(), and numeric_uminus().

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 197 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 198 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 199 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 196 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_SIGN

#define NUMERIC_SIGN (   n)
Value:
(((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
NUMERIC_NEG : NUMERIC_POS) : NUMERIC_FLAGBITS(n))
#define NUMERIC_POS
Definition: numeric.c:165
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:170
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:191
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:172

Definition at line 207 of file numeric.c.

Referenced by cmp_numerics(), init_var_from_num(), int2int4_sum(), numeric(), numeric_sign(), numeric_uminus(), and set_var_from_num().

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 164 of file numeric.c.

◆ NUMERIC_WEIGHT

#define NUMERIC_WEIGHT (   n)
Value:
(((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
| ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
: ((n)->choice.n_long.n_weight))
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:182
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:196
#define NUMERIC_SHORT_WEIGHT_MASK
Definition: numeric.c:197

Definition at line 215 of file numeric.c.

Referenced by cmp_numerics(), hash_numeric(), hash_numeric_extended(), init_var_from_num(), int2int4_sum(), make_result(), numeric(), and set_var_from_num().

◆ NumericAbbrevGetDatum

#define NumericAbbrevGetDatum (   X)    ((Datum) SET_4_BYTES(X))

Definition at line 361 of file numeric.c.

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 100 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

◆ PolyNumAggState

Definition at line 4014 of file numeric.c.

Function Documentation

◆ accum_sum_add()

static void accum_sum_add ( NumericSumAccum accum,
const NumericVar var1 
)
static

Definition at line 8903 of file numeric.c.

References accum_sum_carry(), accum_sum_rescale(), NumericVar::digits, i, NBASE, NumericVar::ndigits, NumericSumAccum::neg_digits, NumericSumAccum::num_uncarried, NUMERIC_POS, NumericSumAccum::pos_digits, NumericVar::sign, NumericVar::weight, and NumericSumAccum::weight.

Referenced by accum_sum_combine(), do_numeric_accum(), do_numeric_discard(), int8_avg_deserialize(), numeric_avg_deserialize(), numeric_deserialize(), numeric_poly_deserialize(), and numeric_stddev_pop().

8904 {
8905  int32 *accum_digits;
8906  int i,
8907  val_i;
8908  int val_ndigits;
8909  NumericDigit *val_digits;
8910 
8911  /*
8912  * If we have accumulated too many values since the last carry
8913  * propagation, do it now, to avoid overflowing. (We could allow more
8914  * than NBASE - 1, if we reserved two extra digits, rather than one, for
8915  * carry propagation. But even with NBASE - 1, this needs to be done so
8916  * seldom, that the performance difference is negligible.)
8917  */
8918  if (accum->num_uncarried == NBASE - 1)
8919  accum_sum_carry(accum);
8920 
8921  /*
8922  * Adjust the weight or scale of the old value, so that it can accommodate
8923  * the new value.
8924  */
8925  accum_sum_rescale(accum, val);
8926 
8927  /* */
8928  if (val->sign == NUMERIC_POS)
8929  accum_digits = accum->pos_digits;
8930  else
8931  accum_digits = accum->neg_digits;
8932 
8933  /* copy these values into local vars for speed in loop */
8934  val_ndigits = val->ndigits;
8935  val_digits = val->digits;
8936 
8937  i = accum->weight - val->weight;
8938  for (val_i = 0; val_i < val_ndigits; val_i++)
8939  {
8940  accum_digits[i] += (int32) val_digits[val_i];
8941  i++;
8942  }
8943 
8944  accum->num_uncarried++;
8945 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:9024
#define NUMERIC_POS
Definition: numeric.c:165
int32 * neg_digits
Definition: numeric.c:345
int num_uncarried
Definition: numeric.c:342
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:8951
signed int int32
Definition: c.h:294
int16 NumericDigit
Definition: numeric.c:100
#define NBASE
Definition: numeric.c:94
int i
int32 * pos_digits
Definition: numeric.c:344
long val
Definition: informix.c:689

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 8951 of file numeric.c.

References Assert, NumericSumAccum::have_carry_space, i, NBASE, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, NumericSumAccum::num_uncarried, and NumericSumAccum::pos_digits.

Referenced by accum_sum_add(), and accum_sum_final().

8952 {
8953  int i;
8954  int ndigits;
8955  int32 *dig;
8956  int32 carry;
8957  int32 newdig = 0;
8958 
8959  /*
8960  * If no new values have been added since last carry propagation, nothing
8961  * to do.
8962  */
8963  if (accum->num_uncarried == 0)
8964  return;
8965 
8966  /*
8967  * We maintain that the weight of the accumulator is always one larger
8968  * than needed to hold the current value, before carrying, to make sure
8969  * there is enough space for the possible extra digit when carry is
8970  * propagated. We cannot expand the buffer here, unless we require
8971  * callers of accum_sum_final() to switch to the right memory context.
8972  */
8973  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
8974 
8975  ndigits = accum->ndigits;
8976 
8977  /* Propagate carry in the positive sum */
8978  dig = accum->pos_digits;
8979  carry = 0;
8980  for (i = ndigits - 1; i >= 0; i--)
8981  {
8982  newdig = dig[i] + carry;
8983  if (newdig >= NBASE)
8984  {
8985  carry = newdig / NBASE;
8986  newdig -= carry * NBASE;
8987  }
8988  else
8989  carry = 0;
8990  dig[i] = newdig;
8991  }
8992  /* Did we use up the digit reserved for carry propagation? */
8993  if (newdig > 0)
8994  accum->have_carry_space = false;
8995 
8996  /* And the same for the negative sum */
8997  dig = accum->neg_digits;
8998  carry = 0;
8999  for (i = ndigits - 1; i >= 0; i--)
9000  {
9001  newdig = dig[i] + carry;
9002  if (newdig >= NBASE)
9003  {
9004  carry = newdig / NBASE;
9005  newdig -= carry * NBASE;
9006  }
9007  else
9008  carry = 0;
9009  dig[i] = newdig;
9010  }
9011  if (newdig > 0)
9012  accum->have_carry_space = false;
9013 
9014  accum->num_uncarried = 0;
9015 }
int32 * neg_digits
Definition: numeric.c:345
int num_uncarried
Definition: numeric.c:342
signed int int32
Definition: c.h:294
bool have_carry_space
Definition: numeric.c:343
#define NBASE
Definition: numeric.c:94
#define Assert(condition)
Definition: c.h:680
int i
int32 * pos_digits
Definition: numeric.c:344

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 9181 of file numeric.c.

References accum_sum_add(), accum_sum_final(), free_var(), and init_var.

Referenced by int8_avg_combine(), numeric_avg_combine(), numeric_combine(), and numeric_poly_combine().

9182 {
9183  NumericVar tmp_var;
9184 
9185  init_var(&tmp_var);
9186 
9187  accum_sum_final(accum2, &tmp_var);
9188  accum_sum_add(accum, &tmp_var);
9189 
9190  free_var(&tmp_var);
9191 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:9113
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8903
static void free_var(NumericVar *var)
Definition: numeric.c:5489
#define init_var(v)
Definition: numeric.c:452

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 9164 of file numeric.c.

References NumericSumAccum::dscale, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, NumericSumAccum::num_uncarried, palloc(), NumericSumAccum::pos_digits, and NumericSumAccum::weight.

Referenced by int8_avg_combine(), numeric_avg_combine(), numeric_combine(), and numeric_poly_combine().

9165 {
9166  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
9167  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
9168 
9169  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
9170  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
9171  dst->num_uncarried = src->num_uncarried;
9172  dst->ndigits = src->ndigits;
9173  dst->weight = src->weight;
9174  dst->dscale = src->dscale;
9175 }
int32 * neg_digits
Definition: numeric.c:345
int num_uncarried
Definition: numeric.c:342
signed int int32
Definition: c.h:294
void * palloc(Size size)
Definition: mcxt.c:835
int32 * pos_digits
Definition: numeric.c:344

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 9113 of file numeric.c.

References accum_sum_carry(), add_var(), Assert, NumericVar::buf, digitbuf_alloc, NumericVar::digits, NumericVar::dscale, NumericSumAccum::dscale, i, init_var, NBASE, NumericVar::ndigits, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, NUMERIC_NEG, NUMERIC_POS, NumericSumAccum::pos_digits, set_var_from_var(), NumericVar::sign, strip_var(), NumericVar::weight, and NumericSumAccum::weight.

Referenced by accum_sum_combine(), int8_avg_serialize(), numeric_avg(), numeric_avg_serialize(), numeric_poly_serialize(), numeric_serialize(), numeric_stddev_internal(), and numeric_sum().

9114 {
9115  int i;
9116  NumericVar pos_var;
9117  NumericVar neg_var;
9118 
9119  if (accum->ndigits == 0)
9120  {
9121  set_var_from_var(&const_zero, result);
9122  return;
9123  }
9124 
9125  /* Perform final carry */
9126  accum_sum_carry(accum);
9127 
9128  /* Create NumericVars representing the positive and negative sums */
9129  init_var(&pos_var);
9130  init_var(&neg_var);
9131 
9132  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
9133  pos_var.weight = neg_var.weight = accum->weight;
9134  pos_var.dscale = neg_var.dscale = accum->dscale;
9135  pos_var.sign = NUMERIC_POS;
9136  neg_var.sign = NUMERIC_NEG;
9137 
9138  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
9139  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
9140 
9141  for (i = 0; i < accum->ndigits; i++)
9142  {
9143  Assert(accum->pos_digits[i] < NBASE);
9144  pos_var.digits[i] = (int16) accum->pos_digits[i];
9145 
9146  Assert(accum->neg_digits[i] < NBASE);
9147  neg_var.digits[i] = (int16) accum->neg_digits[i];
9148  }
9149 
9150  /* And add them together */
9151  add_var(&pos_var, &neg_var, result);
9152 
9153  /* Remove leading/trailing zeroes */
9154  strip_var(result);
9155 }
signed short int16
Definition: c.h:293
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
static void strip_var(NumericVar *var)
Definition: numeric.c:8846
int32 * neg_digits
Definition: numeric.c:345
#define digitbuf_alloc(ndigits)
Definition: numeric.c:444
int ndigits
Definition: numeric.c:272
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:8951
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
NumericDigit * buf
Definition: numeric.c:276
#define NBASE
Definition: numeric.c:94
static const NumericVar const_zero
Definition: numeric.c:372
#define Assert(condition)
Definition: c.h:680
NumericDigit * digits
Definition: numeric.c:277
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6524
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5739
int32 * pos_digits
Definition: numeric.c:344
#define init_var(v)
Definition: numeric.c:452

◆ accum_sum_rescale()

static void accum_sum_rescale ( NumericSumAccum accum,
const NumericVar val 
)
static

Definition at line 9024 of file numeric.c.

References Assert, NumericVar::dscale, NumericSumAccum::dscale, NumericSumAccum::have_carry_space, NumericVar::ndigits, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, palloc0(), pfree(), NumericSumAccum::pos_digits, NumericVar::weight, and NumericSumAccum::weight.

Referenced by accum_sum_add().

9025 {
9026  int old_weight = accum->weight;
9027  int old_ndigits = accum->ndigits;
9028  int accum_ndigits;
9029  int accum_weight;
9030  int accum_rscale;
9031  int val_rscale;
9032 
9033  accum_weight = old_weight;
9034  accum_ndigits = old_ndigits;
9035 
9036  /*
9037  * Does the new value have a larger weight? If so, enlarge the buffers,
9038  * and shift the existing value to the new weight, by adding leading
9039  * zeros.
9040  *
9041  * We enforce that the accumulator always has a weight one larger than
9042  * needed for the inputs, so that we have space for an extra digit at the
9043  * final carry-propagation phase, if necessary.
9044  */
9045  if (val->weight >= accum_weight)
9046  {
9047  accum_weight = val->weight + 1;
9048  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
9049  }
9050 
9051  /*
9052  * Even though the new value is small, we might've used up the space
9053  * reserved for the carry digit in the last call to accum_sum_carry(). If
9054  * so, enlarge to make room for another one.
9055  */
9056  else if (!accum->have_carry_space)
9057  {
9058  accum_weight++;
9059  accum_ndigits++;
9060  }
9061 
9062  /* Is the new value wider on the right side? */
9063  accum_rscale = accum_ndigits - accum_weight - 1;
9064  val_rscale = val->ndigits - val->weight - 1;
9065  if (val_rscale > accum_rscale)
9066  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
9067 
9068  if (accum_ndigits != old_ndigits ||
9069  accum_weight != old_weight)
9070  {
9071  int32 *new_pos_digits;
9072  int32 *new_neg_digits;
9073  int weightdiff;
9074 
9075  weightdiff = accum_weight - old_weight;
9076 
9077  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
9078  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
9079 
9080  if (accum->pos_digits)
9081  {
9082  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
9083  old_ndigits * sizeof(int32));
9084  pfree(accum->pos_digits);
9085 
9086  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
9087  old_ndigits * sizeof(int32));
9088  pfree(accum->neg_digits);
9089  }
9090 
9091  accum->pos_digits = new_pos_digits;
9092  accum->neg_digits = new_neg_digits;
9093 
9094  accum->weight = accum_weight;
9095  accum->ndigits = accum_ndigits;
9096 
9097  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9098  accum->have_carry_space = true;
9099  }
9100 
9101  if (val->dscale > accum->dscale)
9102  accum->dscale = val->dscale;
9103 }
int weight
Definition: numeric.c:273
int32 * neg_digits
Definition: numeric.c:345
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
signed int int32
Definition: c.h:294
void pfree(void *pointer)
Definition: mcxt.c:936
bool have_carry_space
Definition: numeric.c:343
void * palloc0(Size size)
Definition: mcxt.c:864
#define Assert(condition)
Definition: c.h:680
int32 * pos_digits
Definition: numeric.c:344

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 8887 of file numeric.c.

References NumericSumAccum::dscale, i, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, and NumericSumAccum::pos_digits.

Referenced by do_numeric_discard().

8888 {
8889  int i;
8890 
8891  accum->dscale = 0;
8892  for (i = 0; i < accum->ndigits; i++)
8893  {
8894  accum->pos_digits[i] = 0;
8895  accum->neg_digits[i] = 0;
8896  }
8897 }
int32 * neg_digits
Definition: numeric.c:345
int i
int32 * pos_digits
Definition: numeric.c:344

◆ add_abs()

static void add_abs ( const NumericVar var1,
const NumericVar var2,
NumericVar result 
)
static

Definition at line 8511 of file numeric.c.

References Assert, NumericVar::buf, digitbuf_alloc, digitbuf_free, NumericVar::digits, NumericVar::dscale, i, Max, NBASE, NumericVar::ndigits, strip_var(), and NumericVar::weight.

Referenced by add_var(), and sub_var().

8512 {
8513  NumericDigit *res_buf;
8514  NumericDigit *res_digits;
8515  int res_ndigits;
8516  int res_weight;
8517  int res_rscale,
8518  rscale1,
8519  rscale2;
8520  int res_dscale;
8521  int i,
8522  i1,
8523  i2;
8524  int carry = 0;
8525 
8526  /* copy these values into local vars for speed in inner loop */
8527  int var1ndigits = var1->ndigits;
8528  int var2ndigits = var2->ndigits;
8529  NumericDigit *var1digits = var1->digits;
8530  NumericDigit *var2digits = var2->digits;
8531 
8532  res_weight = Max(var1->weight, var2->weight) + 1;
8533 
8534  res_dscale = Max(var1->dscale, var2->dscale);
8535 
8536  /* Note: here we are figuring rscale in base-NBASE digits */
8537  rscale1 = var1->ndigits - var1->weight - 1;
8538  rscale2 = var2->ndigits - var2->weight - 1;
8539  res_rscale = Max(rscale1, rscale2);
8540 
8541  res_ndigits = res_rscale + res_weight + 1;
8542  if (res_ndigits <= 0)
8543  res_ndigits = 1;
8544 
8545  res_buf = digitbuf_alloc(res_ndigits + 1);
8546  res_buf[0] = 0; /* spare digit for later rounding */
8547  res_digits = res_buf + 1;
8548 
8549  i1 = res_rscale + var1->weight + 1;
8550  i2 = res_rscale + var2->weight + 1;
8551  for (i = res_ndigits - 1; i >= 0; i--)
8552  {
8553  i1--;
8554  i2--;
8555  if (i1 >= 0 && i1 < var1ndigits)
8556  carry += var1digits[i1];
8557  if (i2 >= 0 && i2 < var2ndigits)
8558  carry += var2digits[i2];
8559 
8560  if (carry >= NBASE)
8561  {
8562  res_digits[i] = carry - NBASE;
8563  carry = 1;
8564  }
8565  else
8566  {
8567  res_digits[i] = carry;
8568  carry = 0;
8569  }
8570  }
8571 
8572  Assert(carry == 0); /* else we failed to allow for carry out */
8573 
8574  digitbuf_free(result->buf);
8575  result->ndigits = res_ndigits;
8576  result->buf = res_buf;
8577  result->digits = res_digits;
8578  result->weight = res_weight;
8579  result->dscale = res_dscale;
8580 
8581  /* Remove leading/trailing zeroes */
8582  strip_var(result);
8583 }
int weight
Definition: numeric.c:273
static void strip_var(NumericVar *var)
Definition: numeric.c:8846
#define digitbuf_alloc(ndigits)
Definition: numeric.c:444
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define digitbuf_free(buf)
Definition: numeric.c:446
int16 NumericDigit
Definition: numeric.c:100
NumericDigit * buf
Definition: numeric.c:276
#define NBASE
Definition: numeric.c:94
#define Assert(condition)
Definition: c.h:680
NumericDigit * digits
Definition: numeric.c:277
int i
#define Max(x, y)
Definition: numeric.c:11

◆ add_var()

static void add_var ( const NumericVar var1,
const NumericVar var2,
NumericVar result 
)
static

Definition at line 6524 of file numeric.c.

References add_abs(), cmp_abs(), NumericVar::dscale, Max, NUMERIC_NEG, NUMERIC_POS, NumericVar::sign, sub_abs(), and zero_var().

Referenced by accum_sum_final(), ceil_var(), compute_bucket(), exp_var(), generate_series_step_numeric(), ln_var(), numeric_add(), numeric_inc(), sqrt_var(), and width_bucket_numeric().

6525 {
6526  /*
6527  * Decide on the signs of the two variables what to do
6528  */
6529  if (var1->sign == NUMERIC_POS)
6530  {
6531  if (var2->sign == NUMERIC_POS)
6532  {
6533  /*
6534  * Both are positive result = +(ABS(var1) + ABS(var2))
6535  */
6536  add_abs(var1, var2, result);
6537  result->sign = NUMERIC_POS;
6538  }
6539  else
6540  {
6541  /*
6542  * var1 is positive, var2 is negative Must compare absolute values
6543  */
6544  switch (cmp_abs(var1, var2))
6545  {
6546  case 0:
6547  /* ----------
6548  * ABS(var1) == ABS(var2)
6549  * result = ZERO
6550  * ----------
6551  */
6552  zero_var(result);
6553  result->dscale = Max(var1->dscale, var2->dscale);
6554  break;
6555 
6556  case 1:
6557  /* ----------
6558  * ABS(var1) > ABS(var2)
6559  * result = +(ABS(var1) - ABS(var2))
6560  * ----------
6561  */
6562  sub_abs(var1, var2, result);
6563  result->sign = NUMERIC_POS;
6564  break;
6565 
6566  case -1:
6567  /* ----------
6568  * ABS(var1) < ABS(var2)
6569  * result = -(ABS(var2) - ABS(var1))
6570  * ----------
6571  */
6572  sub_abs(var2, var1, result);
6573  result->sign = NUMERIC_NEG;
6574  break;
6575  }
6576  }
6577  }
6578  else
6579  {
6580  if (var2->sign == NUMERIC_POS)
6581  {
6582  /* ----------
6583  * var1 is negative, var2 is positive
6584  * Must compare absolute values
6585  * ----------
6586  */
6587  switch (cmp_abs(var1, var2))
6588  {
6589  case 0:
6590  /* ----------
6591  * ABS(var1) == ABS(var2)
6592  * result = ZERO
6593  * ----------
6594  */
6595  zero_var(result);
6596  result->dscale = Max(var1->dscale, var2->dscale);
6597  break;
6598 
6599  case 1:
6600  /* ----------
6601  * ABS(var1) > ABS(var2)
6602  * result = -(ABS(var1) - ABS(var2))
6603  * ----------
6604  */
6605  sub_abs(var1, var2, result);
6606  result->sign = NUMERIC_NEG;
6607  break;
6608 
6609  case -1:
6610  /* ----------
6611  * ABS(var1) < ABS(var2)
6612  * result = +(ABS(var2) - ABS(var1))
6613  * ----------
6614  */
6615  sub_abs(var2, var1, result);
6616  result->sign = NUMERIC_POS;
6617  break;
6618  }
6619  }
6620  else
6621  {
6622  /* ----------
6623  * Both are negative
6624  * result = -(ABS(var1) + ABS(var2))
6625  * ----------
6626  */
6627  add_abs(var1, var2, result);
6628  result->sign = NUMERIC_NEG;
6629  }
6630  }
6631 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8596
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8511
#define NUMERIC_POS
Definition: numeric.c:165
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static void zero_var(NumericVar *var)
Definition: numeric.c:5505
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8433
#define Max(x, y)
Definition: numeric.c:11

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 5473 of file numeric.c.

References NumericVar::buf, digitbuf_alloc, digitbuf_free, NumericVar::digits, and NumericVar::ndigits.

Referenced by div_var(), div_var_fast(), int64_to_numericvar(), mul_var(), numeric_recv(), set_var_from_num(), set_var_from_str(), and sqrt_var().

5474 {
5475  digitbuf_free(var->buf);
5476  var->buf = digitbuf_alloc(ndigits + 1);
5477  var->buf[0] = 0; /* spare digit for rounding */
5478  var->digits = var->buf + 1;
5479  var->ndigits = ndigits;
5480 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:444
int ndigits
Definition: numeric.c:272
#define digitbuf_free(buf)
Definition: numeric.c:446
NumericDigit * buf
Definition: numeric.c:276
NumericDigit * digits
Definition: numeric.c:277

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

Definition at line 6091 of file numeric.c.

References DEC_DIGITS, NumericVar::digits, ereport, errcode(), errdetail(), errmsg(), ERROR, i, maxdigits, NumericVar::ndigits, round_var(), scale, VARHDRSZ, and NumericVar::weight.

Referenced by numeric(), numeric_in(), and numeric_recv().

6092 {
6093  int precision;
6094  int scale;
6095  int maxdigits;
6096  int ddigits;
6097  int i;
6098 
6099  /* Do nothing if we have a default typmod (-1) */
6100  if (typmod < (int32) (VARHDRSZ))
6101  return;
6102 
6103  typmod -= VARHDRSZ;
6104  precision = (typmod >> 16) & 0xffff;
6105  scale = typmod & 0xffff;
6106  maxdigits = precision - scale;
6107 
6108  /* Round to target scale (and set var->dscale) */
6109  round_var(var, scale);
6110 
6111  /*
6112  * Check for overflow - note we can't do this before rounding, because
6113  * rounding could raise the weight. Also note that the var's weight could
6114  * be inflated by leading zeroes, which will be stripped before storage
6115  * but perhaps might not have been yet. In any case, we must recognize a
6116  * true zero, whose weight doesn't mean anything.
6117  */
6118  ddigits = (var->weight + 1) * DEC_DIGITS;
6119  if (ddigits > maxdigits)
6120  {
6121  /* Determine true weight; and check for all-zero result */
6122  for (i = 0; i < var->ndigits; i++)
6123  {
6124  NumericDigit dig = var->digits[i];
6125 
6126  if (dig)
6127  {
6128  /* Adjust for any high-order decimal zero digits */
6129 #if DEC_DIGITS == 4
6130  if (dig < 10)
6131  ddigits -= 3;
6132  else if (dig < 100)
6133  ddigits -= 2;
6134  else if (dig < 1000)
6135  ddigits -= 1;
6136 #elif DEC_DIGITS == 2
6137  if (dig < 10)
6138  ddigits -= 1;
6139 #elif DEC_DIGITS == 1
6140  /* no adjustment */
6141 #else
6142 #error unsupported NBASE
6143 #endif
6144  if (ddigits > maxdigits)
6145  ereport(ERROR,
6146  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6147  errmsg("numeric field overflow"),
6148  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6149  precision, scale,
6150  /* Display 10^0 as 1 */
6151  maxdigits ? "10^" : "",
6152  maxdigits ? maxdigits : 1
6153  )));
6154  break;
6155  }
6156  ddigits -= DEC_DIGITS;
6157  }
6158  }
6159 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8678
int weight
Definition: numeric.c:273
#define VARHDRSZ
Definition: c.h:503
int errcode(int sqlerrcode)
Definition: elog.c:575
int scale
Definition: pgbench.c:111
int ndigits
Definition: numeric.c:272
signed int int32
Definition: c.h:294
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:100
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
int maxdigits
Definition: informix.c:690
NumericDigit * digits
Definition: numeric.c:277
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define DEC_DIGITS
Definition: numeric.c:96

◆ ceil_var()

static void ceil_var ( const NumericVar var,
NumericVar result 
)
static

Definition at line 7637 of file numeric.c.

References add_var(), cmp_var(), free_var(), init_var, NUMERIC_POS, set_var_from_var(), NumericVar::sign, and trunc_var().

Referenced by numeric_ceil().

7638 {
7639  NumericVar tmp;
7640 
7641  init_var(&tmp);
7642  set_var_from_var(var, &tmp);
7643 
7644  trunc_var(&tmp, 0);
7645 
7646  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
7647  add_var(&tmp, &const_one, &tmp);
7648 
7649  set_var_from_var(&tmp, result);
7650  free_var(&tmp);
7651 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8784
static const NumericVar const_one
Definition: numeric.c:376
#define NUMERIC_POS
Definition: numeric.c:165
int sign
Definition: numeric.c:274
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6466
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6524
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5739
#define init_var(v)
Definition: numeric.c:452

◆ cmp_abs()

static int cmp_abs ( const NumericVar var1,
const NumericVar var2 
)
static

Definition at line 8433 of file numeric.c.

References cmp_abs_common(), NumericVar::digits, NumericVar::ndigits, and NumericVar::weight.

Referenced by add_var(), and sub_var().

8434 {
8435  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
8436  var2->digits, var2->ndigits, var2->weight);
8437 }
int weight
Definition: numeric.c:273
int ndigits
Definition: numeric.c:272
NumericDigit * digits
Definition: numeric.c:277
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8447

◆ cmp_abs_common()

static int cmp_abs_common ( const NumericDigit var1digits,
int  var1ndigits,
int  var1weight,
const NumericDigit var2digits,
int  var2ndigits,
int  var2weight 
)
static

Definition at line 8447 of file numeric.c.

References stat.

Referenced by cmp_abs(), and cmp_var_common().

8449 {
8450  int i1 = 0;
8451  int i2 = 0;
8452 
8453  /* Check any digits before the first common digit */
8454 
8455  while (var1weight > var2weight && i1 < var1ndigits)
8456  {
8457  if (var1digits[i1++] != 0)
8458  return 1;
8459  var1weight--;
8460  }
8461  while (var2weight > var1weight && i2 < var2ndigits)
8462  {
8463  if (var2digits[i2++] != 0)
8464  return -1;
8465  var2weight--;
8466  }
8467 
8468  /* At this point, either w1 == w2 or we've run out of digits */
8469 
8470  if (var1weight == var2weight)
8471  {
8472  while (i1 < var1ndigits && i2 < var2ndigits)
8473  {
8474  int stat = var1digits[i1++] - var2digits[i2++];
8475 
8476  if (stat)
8477  {
8478  if (stat > 0)
8479  return 1;
8480  return -1;
8481  }
8482  }
8483  }
8484 
8485  /*
8486  * At this point, we've run out of digits on one side or the other; so any
8487  * remaining nonzero digits imply that side is larger
8488  */
8489  while (i1 < var1ndigits)
8490  {
8491  if (var1digits[i1++] != 0)
8492  return 1;
8493  }
8494  while (i2 < var2ndigits)
8495  {
8496  if (var2digits[i2++] != 0)
8497  return -1;
8498  }
8499 
8500  return 0;
8501 }
#define stat(a, b)
Definition: win32_port.h:266

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2137 of file numeric.c.

References cmp_var_common(), NUMERIC_DIGITS, NUMERIC_IS_NAN, NUMERIC_NDIGITS, NUMERIC_SIGN, and NUMERIC_WEIGHT.

Referenced by numeric_cmp(), numeric_eq(), numeric_fast_cmp(), numeric_ge(), numeric_gt(), numeric_larger(), numeric_le(), numeric_lt(), numeric_ne(), numeric_smaller(), and width_bucket_numeric().

2138 {
2139  int result;
2140 
2141  /*
2142  * We consider all NANs to be equal and larger than any non-NAN. This is
2143  * somewhat arbitrary; the important thing is to have a consistent sort
2144  * order.
2145  */
2146  if (NUMERIC_IS_NAN(num1))
2147  {
2148  if (NUMERIC_IS_NAN(num2))
2149  result = 0; /* NAN = NAN */
2150  else
2151  result = 1; /* NAN > non-NAN */
2152  }
2153  else if (NUMERIC_IS_NAN(num2))
2154  {
2155  result = -1; /* non-NAN < NAN */
2156  }
2157  else
2158  {
2159  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2160  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2161  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2162  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2163  }
2164 
2165  return result;
2166 }
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
#define NUMERIC_SIGN(n)
Definition: numeric.c:207
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
Definition: numeric.c:6481
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171

◆ cmp_var()

static int cmp_var ( const NumericVar var1,
const NumericVar var2 
)
static

Definition at line 6466 of file numeric.c.

References cmp_var_common(), NumericVar::digits, NumericVar::ndigits, NumericVar::sign, and NumericVar::weight.

Referenced by ceil_var(), compute_bucket(), estimate_ln_dweight(), floor_var(), generate_series_step_numeric(), ln_var(), numeric_power(), numeric_stddev_internal(), power_var(), and sqrt_var().

6467 {
6468  return cmp_var_common(var1->digits, var1->ndigits,
6469  var1->weight, var1->sign,
6470  var2->digits, var2->ndigits,
6471  var2->weight, var2->sign);
6472 }
int weight
Definition: numeric.c:273
int ndigits
Definition: numeric.c:272
int sign
Definition: numeric.c:274
static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
Definition: numeric.c:6481
NumericDigit * digits
Definition: numeric.c:277

◆ cmp_var_common()

static int cmp_var_common ( const NumericDigit var1digits,
int  var1ndigits,
int  var1weight,
int  var1sign,
const NumericDigit var2digits,
int  var2ndigits,
int  var2weight,
int  var2sign 
)
static

Definition at line 6481 of file numeric.c.

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

6485 {
6486  if (var1ndigits == 0)
6487  {
6488  if (var2ndigits == 0)
6489  return 0;
6490  if (var2sign == NUMERIC_NEG)
6491  return 1;
6492  return -1;
6493  }
6494  if (var2ndigits == 0)
6495  {
6496  if (var1sign == NUMERIC_POS)
6497  return 1;
6498  return -1;
6499  }
6500 
6501  if (var1sign == NUMERIC_POS)
6502  {
6503  if (var2sign == NUMERIC_NEG)
6504  return 1;
6505  return cmp_abs_common(var1digits, var1ndigits, var1weight,
6506  var2digits, var2ndigits, var2weight);
6507  }
6508 
6509  if (var2sign == NUMERIC_POS)
6510  return -1;
6511 
6512  return cmp_abs_common(var2digits, var2ndigits, var2weight,
6513  var1digits, var1ndigits, var1weight);
6514 }
#define NUMERIC_POS
Definition: numeric.c:165
#define NUMERIC_NEG
Definition: numeric.c:166
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8447

◆ compute_bucket()

static void compute_bucket ( Numeric  operand,
Numeric  bound1,
Numeric  bound2,
const NumericVar count_var,
NumericVar result_var 
)
static

Definition at line 1564 of file numeric.c.

References add_var(), cmp_var(), div_var(), NumericVar::dscale, floor_var(), free_var(), init_var_from_num(), mul_var(), select_div_scale(), and sub_var().

Referenced by width_bucket_numeric().

1566 {
1567  NumericVar bound1_var;
1568  NumericVar bound2_var;
1569  NumericVar operand_var;
1570 
1571  init_var_from_num(bound1, &bound1_var);
1572  init_var_from_num(bound2, &bound2_var);
1573  init_var_from_num(operand, &operand_var);
1574 
1575  if (cmp_var(&bound1_var, &bound2_var) < 0)
1576  {
1577  sub_var(&operand_var, &bound1_var, &operand_var);
1578  sub_var(&bound2_var, &bound1_var, &bound2_var);
1579  div_var(&operand_var, &bound2_var, result_var,
1580  select_div_scale(&operand_var, &bound2_var), true);
1581  }
1582  else
1583  {
1584  sub_var(&bound1_var, &operand_var, &operand_var);
1585  sub_var(&bound1_var, &bound2_var, &bound1_var);
1586  div_var(&operand_var, &bound1_var, result_var,
1587  select_div_scale(&operand_var, &bound1_var), true);
1588  }
1589 
1590  mul_var(result_var, count_var, result_var,
1591  result_var->dscale + count_var->dscale);
1592  add_var(result_var, &const_one, result_var);
1593  floor_var(result_var, result_var);
1594 
1595  free_var(&bound1_var);
1596  free_var(&bound2_var);
1597  free_var(&operand_var);
1598 }
static const NumericVar const_one
Definition: numeric.c:376
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:6959
int dscale
Definition: numeric.c:275
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7539
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5722
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6466
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6762
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6524
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6641
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:7661

◆ div_var()

static void div_var ( const NumericVar var1,
const NumericVar var2,
NumericVar result,
int  rscale,
bool  round 
)
static

Definition at line 6959 of file numeric.c.

References alloc_var(), Assert, DEC_DIGITS, NumericVar::digits, NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, HALF_NBASE, i, Max, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, palloc0(), pfree(), round_var(), NumericVar::sign, strip_var(), trunc_var(), NumericVar::weight, and zero_var().

Referenced by compute_bucket(), get_str_from_var_sci(), mod_var(), numeric_div(), numeric_div_trunc(), numeric_stddev_internal(), and power_var_int().

6961 {
6962  int div_ndigits;
6963  int res_ndigits;
6964  int res_sign;
6965  int res_weight;
6966  int carry;
6967  int borrow;
6968  int divisor1;
6969  int divisor2;
6970  NumericDigit *dividend;
6971  NumericDigit *divisor;
6972  NumericDigit *res_digits;
6973  int i;
6974  int j;
6975 
6976  /* copy these values into local vars for speed in inner loop */
6977  int var1ndigits = var1->ndigits;
6978  int var2ndigits = var2->ndigits;
6979 
6980  /*
6981  * First of all division by zero check; we must not be handed an
6982  * unnormalized divisor.
6983  */
6984  if (var2ndigits == 0 || var2->digits[0] == 0)
6985  ereport(ERROR,
6986  (errcode(ERRCODE_DIVISION_BY_ZERO),
6987  errmsg("division by zero")));
6988 
6989  /*
6990  * Now result zero check
6991  */
6992  if (var1ndigits == 0)
6993  {
6994  zero_var(result);
6995  result->dscale = rscale;
6996  return;
6997  }
6998 
6999  /*
7000  * Determine the result sign, weight and number of digits to calculate.
7001  * The weight figured here is correct if the emitted quotient has no
7002  * leading zero digits; otherwise strip_var() will fix things up.
7003  */
7004  if (var1->sign == var2->sign)
7005  res_sign = NUMERIC_POS;
7006  else
7007  res_sign = NUMERIC_NEG;
7008  res_weight = var1->weight - var2->weight;
7009  /* The number of accurate result digits we need to produce: */
7010  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7011  /* ... but always at least 1 */
7012  res_ndigits = Max(res_ndigits, 1);
7013  /* If rounding needed, figure one more digit to ensure correct result */
7014  if (round)
7015  res_ndigits++;
7016 
7017  /*
7018  * The working dividend normally requires res_ndigits + var2ndigits
7019  * digits, but make it at least var1ndigits so we can load all of var1
7020  * into it. (There will be an additional digit dividend[0] in the
7021  * dividend space, but for consistency with Knuth's notation we don't
7022  * count that in div_ndigits.)
7023  */
7024  div_ndigits = res_ndigits + var2ndigits;
7025  div_ndigits = Max(div_ndigits, var1ndigits);
7026 
7027  /*
7028  * We need a workspace with room for the working dividend (div_ndigits+1
7029  * digits) plus room for the possibly-normalized divisor (var2ndigits
7030  * digits). It is convenient also to have a zero at divisor[0] with the
7031  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
7032  * digits into the workspace also allows us to realloc the result (which
7033  * might be the same as either input var) before we begin the main loop.
7034  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
7035  * any additional dividend positions beyond var1ndigits, start out 0.
7036  */
7037  dividend = (NumericDigit *)
7038  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
7039  divisor = dividend + (div_ndigits + 1);
7040  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
7041  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
7042 
7043  /*
7044  * Now we can realloc the result to hold the generated quotient digits.
7045  */
7046  alloc_var(result, res_ndigits);
7047  res_digits = result->digits;
7048 
7049  if (var2ndigits == 1)
7050  {
7051  /*
7052  * If there's only a single divisor digit, we can use a fast path (cf.
7053  * Knuth section 4.3.1 exercise 16).
7054  */
7055  divisor1 = divisor[1];
7056  carry = 0;
7057  for (i = 0; i < res_ndigits; i++)
7058  {
7059  carry = carry * NBASE + dividend[i + 1];
7060  res_digits[i] = carry / divisor1;
7061  carry = carry % divisor1;
7062  }
7063  }
7064  else
7065  {
7066  /*
7067  * The full multiple-place algorithm is taken from Knuth volume 2,
7068  * Algorithm 4.3.1D.
7069  *
7070  * We need the first divisor digit to be >= NBASE/2. If it isn't,
7071  * make it so by scaling up both the divisor and dividend by the
7072  * factor "d". (The reason for allocating dividend[0] above is to
7073  * leave room for possible carry here.)
7074  */
7075  if (divisor[1] < HALF_NBASE)
7076  {
7077  int d = NBASE / (divisor[1] + 1);
7078 
7079  carry = 0;
7080  for (i = var2ndigits; i > 0; i--)
7081  {
7082  carry += divisor[i] * d;
7083  divisor[i] = carry % NBASE;
7084  carry = carry / NBASE;
7085  }
7086  Assert(carry == 0);
7087  carry = 0;
7088  /* at this point only var1ndigits of dividend can be nonzero */
7089  for (i = var1ndigits; i >= 0; i--)
7090  {
7091  carry += dividend[i] * d;
7092  dividend[i] = carry % NBASE;
7093  carry = carry / NBASE;
7094  }
7095  Assert(carry == 0);
7096  Assert(divisor[1] >= HALF_NBASE);
7097  }
7098  /* First 2 divisor digits are used repeatedly in main loop */
7099  divisor1 = divisor[1];
7100  divisor2 = divisor[2];
7101 
7102  /*
7103  * Begin the main loop. Each iteration of this loop produces the j'th
7104  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7105  * divisor; this is essentially the same as the common manual
7106  * procedure for long division.
7107  */
7108  for (j = 0; j < res_ndigits; j++)
7109  {
7110  /* Estimate quotient digit from the first two dividend digits */
7111  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7112  int qhat;
7113 
7114  /*
7115  * If next2digits are 0, then quotient digit must be 0 and there's
7116  * no need to adjust the working dividend. It's worth testing
7117  * here to fall out ASAP when processing trailing zeroes in a
7118  * dividend.
7119  */
7120  if (next2digits == 0)
7121  {
7122  res_digits[j] = 0;
7123  continue;
7124  }
7125 
7126  if (dividend[j] == divisor1)
7127  qhat = NBASE - 1;
7128  else
7129  qhat = next2digits / divisor1;
7130 
7131  /*
7132  * Adjust quotient digit if it's too large. Knuth proves that
7133  * after this step, the quotient digit will be either correct or
7134  * just one too large. (Note: it's OK to use dividend[j+2] here
7135  * because we know the divisor length is at least 2.)
7136  */
7137  while (divisor2 * qhat >
7138  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7139  qhat--;
7140 
7141  /* As above, need do nothing more when quotient digit is 0 */
7142  if (qhat > 0)
7143  {
7144  /*
7145  * Multiply the divisor by qhat, and subtract that from the
7146  * working dividend. "carry" tracks the multiplication,
7147  * "borrow" the subtraction (could we fold these together?)
7148  */
7149  carry = 0;
7150  borrow = 0;
7151  for (i = var2ndigits; i >= 0; i--)
7152  {
7153  carry += divisor[i] * qhat;
7154  borrow -= carry % NBASE;
7155  carry = carry / NBASE;
7156  borrow += dividend[j + i];
7157  if (borrow < 0)
7158  {
7159  dividend[j + i] = borrow + NBASE;
7160  borrow = -1;
7161  }
7162  else
7163  {
7164  dividend[j + i] = borrow;
7165  borrow = 0;
7166  }
7167  }
7168  Assert(carry == 0);
7169 
7170  /*
7171  * If we got a borrow out of the top dividend digit, then
7172  * indeed qhat was one too large. Fix it, and add back the
7173  * divisor to correct the working dividend. (Knuth proves
7174  * that this will occur only about 3/NBASE of the time; hence,
7175  * it's a good idea to test this code with small NBASE to be
7176  * sure this section gets exercised.)
7177  */
7178  if (borrow)
7179  {
7180  qhat--;
7181  carry = 0;
7182  for (i = var2ndigits; i >= 0; i--)
7183  {
7184  carry += dividend[j + i] + divisor[i];
7185  if (carry >= NBASE)
7186  {
7187  dividend[j + i] = carry - NBASE;
7188  carry = 1;
7189  }
7190  else
7191  {
7192  dividend[j + i] = carry;
7193  carry = 0;
7194  }
7195  }
7196  /* A carry should occur here to cancel the borrow above */
7197  Assert(carry == 1);
7198  }
7199  }
7200 
7201  /* And we're done with this quotient digit */
7202  res_digits[j] = qhat;
7203  }
7204  }
7205 
7206  pfree(dividend);
7207 
7208  /*
7209  * Finally, round or truncate the result to the requested precision.
7210  */
7211  result->weight = res_weight;
7212  result->sign = res_sign;
7213 
7214  /* Round or truncate to target rscale (and set result->dscale) */
7215  if (round)
7216  round_var(result, rscale);
7217  else
7218  trunc_var(result, rscale);
7219 
7220  /* Strip leading and trailing zeroes */
7221  strip_var(result);
7222 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8678
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8784
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
static void strip_var(NumericVar *var)
Definition: numeric.c:8846
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static void zero_var(NumericVar *var)
Definition: numeric.c:5505
void pfree(void *pointer)
Definition: mcxt.c:936
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:100
#define HALF_NBASE
Definition: numeric.c:95
#define ereport(elevel, rest)
Definition: elog.h:122
#define NBASE
Definition: numeric.c:94
void * palloc0(Size size)
Definition: mcxt.c:864
#define Assert(condition)
Definition: c.h:680
NumericDigit * digits
Definition: numeric.c:277
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5473
int i
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:96

◆ div_var_fast()

static void div_var_fast ( const NumericVar var1,
const NumericVar var2,
NumericVar result,
int  rscale,
bool  round 
)
static

Definition at line 7244 of file numeric.c.

References Abs, alloc_var(), Assert, DEC_DIGITS, NumericVar::digits, DIV_GUARD_DIGITS, NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, i, Min, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, palloc0(), pfree(), round_var(), NumericVar::sign, strip_var(), trunc_var(), NumericVar::weight, and zero_var().

Referenced by exp_var(), ln_var(), log_var(), power_var_int(), and sqrt_var().

7246 {
7247  int div_ndigits;
7248  int res_sign;
7249  int res_weight;
7250  int *div;
7251  int qdigit;
7252  int carry;
7253  int maxdiv;
7254  int newdig;
7255  NumericDigit *res_digits;
7256  double fdividend,
7257  fdivisor,
7258  fdivisorinverse,
7259  fquotient;
7260  int qi;
7261  int i;
7262 
7263  /* copy these values into local vars for speed in inner loop */
7264  int var1ndigits = var1->ndigits;
7265  int var2ndigits = var2->ndigits;
7266  NumericDigit *var1digits = var1->digits;
7267  NumericDigit *var2digits = var2->digits;
7268 
7269  /*
7270  * First of all division by zero check; we must not be handed an
7271  * unnormalized divisor.
7272  */
7273  if (var2ndigits == 0 || var2digits[0] == 0)
7274  ereport(ERROR,
7275  (errcode(ERRCODE_DIVISION_BY_ZERO),
7276  errmsg("division by zero")));
7277 
7278  /*
7279  * Now result zero check
7280  */
7281  if (var1ndigits == 0)
7282  {
7283  zero_var(result);
7284  result->dscale = rscale;
7285  return;
7286  }
7287 
7288  /*
7289  * Determine the result sign, weight and number of digits to calculate
7290  */
7291  if (var1->sign == var2->sign)
7292  res_sign = NUMERIC_POS;
7293  else
7294  res_sign = NUMERIC_NEG;
7295  res_weight = var1->weight - var2->weight + 1;
7296  /* The number of accurate result digits we need to produce: */
7297  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7298  /* Add guard digits for roundoff error */
7299  div_ndigits += DIV_GUARD_DIGITS;
7300  if (div_ndigits < DIV_GUARD_DIGITS)
7301  div_ndigits = DIV_GUARD_DIGITS;
7302  /* Must be at least var1ndigits, too, to simplify data-loading loop */
7303  if (div_ndigits < var1ndigits)
7304  div_ndigits = var1ndigits;
7305 
7306  /*
7307  * We do the arithmetic in an array "div[]" of signed int's. Since
7308  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7309  * to avoid normalizing carries immediately.
7310  *
7311  * We start with div[] containing one zero digit followed by the
7312  * dividend's digits (plus appended zeroes to reach the desired precision
7313  * including guard digits). Each step of the main loop computes an
7314  * (approximate) quotient digit and stores it into div[], removing one
7315  * position of dividend space. A final pass of carry propagation takes
7316  * care of any mistaken quotient digits.
7317  */
7318  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7319  for (i = 0; i < var1ndigits; i++)
7320  div[i + 1] = var1digits[i];
7321 
7322  /*
7323  * We estimate each quotient digit using floating-point arithmetic, taking
7324  * the first four digits of the (current) dividend and divisor. This must
7325  * be float to avoid overflow. The quotient digits will generally be off
7326  * by no more than one from the exact answer.
7327  */
7328  fdivisor = (double) var2digits[0];
7329  for (i = 1; i < 4; i++)
7330  {
7331  fdivisor *= NBASE;
7332  if (i < var2ndigits)
7333  fdivisor += (double) var2digits[i];
7334  }
7335  fdivisorinverse = 1.0 / fdivisor;
7336 
7337  /*
7338  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7339  * when this threatens to exceed INT_MAX, we take the time to propagate
7340  * carries. Furthermore, we need to ensure that overflow doesn't occur
7341  * during the carry propagation passes either. The carry values may have
7342  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7343  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7344  *
7345  * To avoid overflow in maxdiv itself, it represents the max absolute
7346  * value divided by NBASE-1, ie, at the top of the loop it is known that
7347  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7348  *
7349  * Actually, though, that holds good only for div[] entries after div[qi];
7350  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7351  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7352  * beyond the limit. This does not cause problems, as explained below.
7353  */
7354  maxdiv = 1;
7355 
7356  /*
7357  * Outer loop computes next quotient digit, which will go into div[qi]
7358  */
7359  for (qi = 0; qi < div_ndigits; qi++)
7360  {
7361  /* Approximate the current dividend value */
7362  fdividend = (double) div[qi];
7363  for (i = 1; i < 4; i++)
7364  {
7365  fdividend *= NBASE;
7366  if (qi + i <= div_ndigits)
7367  fdividend += (double) div[qi + i];
7368  }
7369  /* Compute the (approximate) quotient digit */
7370  fquotient = fdividend * fdivisorinverse;
7371  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7372  (((int) fquotient) - 1); /* truncate towards -infinity */
7373 
7374  if (qdigit != 0)
7375  {
7376  /* Do we need to normalize now? */
7377  maxdiv += Abs(qdigit);
7378  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7379  {
7380  /* Yes, do it */
7381  carry = 0;
7382  for (i = div_ndigits; i > qi; i--)
7383  {
7384  newdig = div[i] + carry;
7385  if (newdig < 0)
7386  {
7387  carry = -((-newdig - 1) / NBASE) - 1;
7388  newdig -= carry * NBASE;
7389  }
7390  else if (newdig >= NBASE)
7391  {
7392  carry = newdig / NBASE;
7393  newdig -= carry * NBASE;
7394  }
7395  else
7396  carry = 0;
7397  div[i] = newdig;
7398  }
7399  newdig = div[qi] + carry;
7400  div[qi] = newdig;
7401 
7402  /*
7403  * All the div[] digits except possibly div[qi] are now in the
7404  * range 0..NBASE-1. We do not need to consider div[qi] in
7405  * the maxdiv value anymore, so we can reset maxdiv to 1.
7406  */
7407  maxdiv = 1;
7408 
7409  /*
7410  * Recompute the quotient digit since new info may have
7411  * propagated into the top four dividend digits
7412  */
7413  fdividend = (double) div[qi];
7414  for (i = 1; i < 4; i++)
7415  {
7416  fdividend *= NBASE;
7417  if (qi + i <= div_ndigits)
7418  fdividend += (double) div[qi + i];
7419  }
7420  /* Compute the (approximate) quotient digit */
7421  fquotient = fdividend * fdivisorinverse;
7422  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7423  (((int) fquotient) - 1); /* truncate towards -infinity */
7424  maxdiv += Abs(qdigit);
7425  }
7426 
7427  /*
7428  * Subtract off the appropriate multiple of the divisor.
7429  *
7430  * The digits beyond div[qi] cannot overflow, because we know they
7431  * will fall within the maxdiv limit. As for div[qi] itself, note
7432  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7433  * which would make the new value simply div[qi] mod vardigits[0].
7434  * The lower-order terms in qdigit can change this result by not
7435  * more than about twice INT_MAX/NBASE, so overflow is impossible.
7436  */
7437  if (qdigit != 0)
7438  {
7439  int istop = Min(var2ndigits, div_ndigits - qi + 1);
7440 
7441  for (i = 0; i < istop; i++)
7442  div[qi + i] -= qdigit * var2digits[i];
7443  }
7444  }
7445 
7446  /*
7447  * The dividend digit we are about to replace might still be nonzero.
7448  * Fold it into the next digit position.
7449  *
7450  * There is no risk of overflow here, although proving that requires
7451  * some care. Much as with the argument for div[qi] not overflowing,
7452  * if we consider the first two terms in the numerator and denominator
7453  * of qdigit, we can see that the final value of div[qi + 1] will be
7454  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7455  * Accounting for the lower-order terms is a bit complicated but ends
7456  * up adding not much more than INT_MAX/NBASE to the possible range.
7457  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7458  * in the next loop iteration, it can't be large enough to cause
7459  * overflow in the carry propagation step (if any), either.
7460  *
7461  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7462  * noted above, which means that the product div[qi] * NBASE *can*
7463  * overflow. When that happens, adding it to div[qi + 1] will always
7464  * cause a canceling overflow so that the end result is correct. We
7465  * could avoid the intermediate overflow by doing the multiplication
7466  * and addition in int64 arithmetic, but so far there appears no need.
7467  */
7468  div[qi + 1] += div[qi] * NBASE;
7469 
7470  div[qi] = qdigit;
7471  }
7472 
7473  /*
7474  * Approximate and store the last quotient digit (div[div_ndigits])
7475  */
7476  fdividend = (double) div[qi];
7477  for (i = 1; i < 4; i++)
7478  fdividend *= NBASE;
7479  fquotient = fdividend * fdivisorinverse;
7480  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7481  (((int) fquotient) - 1); /* truncate towards -infinity */
7482  div[qi] = qdigit;
7483 
7484  /*
7485  * Because the quotient digits might be off by one, some of them might be
7486  * -1 or NBASE at this point. The represented value is correct in a
7487  * mathematical sense, but it doesn't look right. We do a final carry
7488  * propagation pass to normalize the digits, which we combine with storing
7489  * the result digits into the output. Note that this is still done at
7490  * full precision w/guard digits.
7491  */
7492  alloc_var(result, div_ndigits + 1);
7493  res_digits = result->digits;
7494  carry = 0;
7495  for (i = div_ndigits; i >= 0; i--)
7496  {
7497  newdig = div[i] + carry;
7498  if (newdig < 0)
7499  {
7500  carry = -((-newdig - 1) / NBASE) - 1;
7501  newdig -= carry * NBASE;
7502  }
7503  else if (newdig >= NBASE)
7504  {
7505  carry = newdig / NBASE;
7506  newdig -= carry * NBASE;
7507  }
7508  else
7509  carry = 0;
7510  res_digits[i] = newdig;
7511  }
7512  Assert(carry == 0);
7513 
7514  pfree(div);
7515 
7516  /*
7517  * Finally, round the result to the requested precision.
7518  */
7519  result->weight = res_weight;
7520  result->sign = res_sign;
7521 
7522  /* Round to target rscale (and set result->dscale) */
7523  if (round)
7524  round_var(result, rscale);
7525  else
7526  trunc_var(result, rscale);
7527 
7528  /* Strip leading and trailing zeroes */
7529  strip_var(result);
7530 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8678
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8784
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
static void strip_var(NumericVar *var)
Definition: numeric.c:8846
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define Min(x, y)
Definition: numeric.c:12
#define Abs(x)
Definition: c.h:832
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static void zero_var(NumericVar *var)
Definition: numeric.c:5505
void pfree(void *pointer)
Definition: mcxt.c:936
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:100
#define ereport(elevel, rest)
Definition: elog.h:122
#define NBASE
Definition: numeric.c:94
void * palloc0(Size size)
Definition: mcxt.c:864
#define Assert(condition)
Definition: c.h:680
NumericDigit * digits
Definition: numeric.c:277
#define DIV_GUARD_DIGITS
Definition: numeric.c:98
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5473
int i
#define DEC_DIGITS
Definition: numeric.c:96

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3330 of file numeric.c.

References accum_sum_add(), NumericAggState::agg_context, NumericAggState::calcSumX2, NumericVar::dscale, init_var, init_var_from_num(), NumericAggState::maxScale, NumericAggState::maxScaleCount, MemoryContextSwitchTo(), mul_var(), NumericAggState::N, NumericAggState::NaNcount, NUMERIC_IS_NAN, NumericAggState::sumX, and NumericAggState::sumX2.

Referenced by int2_accum(), int4_accum(), int8_accum(), int8_avg_accum(), numeric_accum(), and numeric_avg_accum().

3331 {
3332  NumericVar X;
3333  NumericVar X2;
3334  MemoryContext old_context;
3335 
3336  /* Count NaN inputs separately from all else */
3337  if (NUMERIC_IS_NAN(newval))
3338  {
3339  state->NaNcount++;
3340  return;
3341  }
3342 
3343  /* load processed number in short-lived context */
3344  init_var_from_num(newval, &X);
3345 
3346  /*
3347  * Track the highest input dscale that we've seen, to support inverse
3348  * transitions (see do_numeric_discard).
3349  */
3350  if (X.dscale > state->maxScale)
3351  {
3352  state->maxScale = X.dscale;
3353  state->maxScaleCount = 1;
3354  }
3355  else if (X.dscale == state->maxScale)
3356  state->maxScaleCount++;
3357 
3358  /* if we need X^2, calculate that in short-lived context */
3359  if (state->calcSumX2)
3360  {
3361  init_var(&X2);
3362  mul_var(&X, &X, &X2, X.dscale * 2);
3363  }
3364 
3365  /* The rest of this needs to work in the aggregate context */
3366  old_context = MemoryContextSwitchTo(state->agg_context);
3367 
3368  state->N++;
3369 
3370  /* Accumulate sums */
3371  accum_sum_add(&(state->sumX), &X);
3372 
3373  if (state->calcSumX2)
3374  accum_sum_add(&(state->sumX2), &X2);
3375 
3376  MemoryContextSwitchTo(old_context);
3377 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3276
int dscale
Definition: numeric.c:275
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8903
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5722
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6762
NumericSumAccum sumX2
Definition: numeric.c:3279
int64 NaNcount
Definition: numeric.c:3282
int64 maxScaleCount
Definition: numeric.c:3281
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
NumericSumAccum sumX
Definition: numeric.c:3278
#define init_var(v)
Definition: numeric.c:452

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3395 of file numeric.c.

References accum_sum_add(), accum_sum_reset(), NumericAggState::agg_context, Assert, NumericAggState::calcSumX2, NumericVar::dscale, init_var, init_var_from_num(), NumericAggState::maxScale, NumericAggState::maxScaleCount, MemoryContextSwitchTo(), mul_var(), NumericAggState::N, NumericAggState::NaNcount, NUMERIC_IS_NAN, NUMERIC_NEG, NUMERIC_POS, NumericVar::sign, NumericAggState::sumX, and NumericAggState::sumX2.

Referenced by int2_accum_inv(), int4_accum_inv(), int8_accum_inv(), int8_avg_accum_inv(), and numeric_accum_inv().

3396 {
3397  NumericVar X;
3398  NumericVar X2;
3399  MemoryContext old_context;
3400 
3401  /* Count NaN inputs separately from all else */
3402  if (NUMERIC_IS_NAN(newval))
3403  {
3404  state->NaNcount--;
3405  return true;
3406  }
3407 
3408  /* load processed number in short-lived context */
3409  init_var_from_num(newval, &X);
3410 
3411  /*
3412  * state->sumX's dscale is the maximum dscale of any of the inputs.
3413  * Removing the last input with that dscale would require us to recompute
3414  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3415  * no more non-NaN inputs remain at all. So we report a failure instead,
3416  * and force the aggregation to be redone from scratch.
3417  */
3418  if (X.dscale == state->maxScale)
3419  {
3420  if (state->maxScaleCount > 1 || state->maxScale == 0)
3421  {
3422  /*
3423  * Some remaining inputs have same dscale, or dscale hasn't gotten
3424  * above zero anyway
3425  */
3426  state->maxScaleCount--;
3427  }
3428  else if (state->N == 1)
3429  {
3430  /* No remaining non-NaN inputs at all, so reset maxScale */
3431  state->maxScale = 0;
3432  state->maxScaleCount = 0;
3433  }
3434  else
3435  {
3436  /* Correct new maxScale is uncertain, must fail */
3437  return false;
3438  }
3439  }
3440 
3441  /* if we need X^2, calculate that in short-lived context */
3442  if (state->calcSumX2)
3443  {
3444  init_var(&X2);
3445  mul_var(&X, &X, &X2, X.dscale * 2);
3446  }
3447 
3448  /* The rest of this needs to work in the aggregate context */
3449  old_context = MemoryContextSwitchTo(state->agg_context);
3450 
3451  if (state->N-- > 1)
3452  {
3453  /* Negate X, to subtract it from the sum */
3454  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3455  accum_sum_add(&(state->sumX), &X);
3456 
3457  if (state->calcSumX2)
3458  {
3459  /* Negate X^2. X^2 is always positive */
3460  X2.sign = NUMERIC_NEG;
3461  accum_sum_add(&(state->sumX2), &X2);
3462  }
3463  }
3464  else
3465  {
3466  /* Zero the sums */
3467  Assert(state->N == 0);
3468 
3469  accum_sum_reset(&state->sumX);
3470  if (state->calcSumX2)
3471  accum_sum_reset(&state->sumX2);
3472  }
3473 
3474  MemoryContextSwitchTo(old_context);
3475 
3476  return true;
3477 }
#define NUMERIC_POS
Definition: numeric.c:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3276
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8903
int sign
Definition: numeric.c:274
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5722
#define Assert(condition)
Definition: c.h:680
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6762
NumericSumAccum sumX2
Definition: numeric.c:3279
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:8887
int64 NaNcount
Definition: numeric.c:3282
int64 maxScaleCount
Definition: numeric.c:3281
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
NumericSumAccum sumX
Definition: numeric.c:3278
#define init_var(v)
Definition: numeric.c:452

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 7883 of file numeric.c.

References Abs, cmp_var(), DEC_DIGITS, NumericVar::digits, digits, free_var(), init_var, ln_var(), NBASE, NumericVar::ndigits, sub_var(), and NumericVar::weight.

Referenced by log_var(), numeric_ln(), and power_var().

7884 {
7885  int ln_dweight;
7886 
7887  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
7888  cmp_var(var, &const_one_point_one) <= 0)
7889  {
7890  /*
7891  * 0.9 <= var <= 1.1
7892  *
7893  * ln(var) has a negative weight (possibly very large). To get a
7894  * reasonably accurate result, estimate it using ln(1+x) ~= x.
7895  */
7896  NumericVar x;
7897 
7898  init_var(&x);
7899  sub_var(var, &const_one, &x);
7900 
7901  if (x.ndigits > 0)
7902  {
7903  /* Use weight of most significant decimal digit of x */
7904  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
7905  }
7906  else
7907  {
7908  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
7909  ln_dweight = 0;
7910  }
7911 
7912  free_var(&x);
7913  }
7914  else
7915  {
7916  /*
7917  * Estimate the logarithm using the first couple of digits from the
7918  * input number. This will give an accurate result whenever the input
7919  * is not too close to 1.
7920  */
7921  if (var->ndigits > 0)
7922  {
7923  int digits;
7924  int dweight;
7925  double ln_var;
7926 
7927  digits = var->digits[0];
7928  dweight = var->weight * DEC_DIGITS;
7929 
7930  if (var->ndigits > 1)
7931  {
7932  digits = digits * NBASE + var->digits[1];
7933  dweight -= DEC_DIGITS;
7934  }
7935 
7936  /*----------
7937  * We have var ~= digits * 10^dweight
7938  * so ln(var) ~= ln(digits) + dweight * ln(10)
7939  *----------
7940  */
7941  ln_var = log((double) digits) + dweight * 2.302585092994046;
7942  ln_dweight = (int) log10(Abs(ln_var));
7943  }
7944  else
7945  {
7946  /* Caller should fail on ln(0), but for the moment return zero */
7947  ln_dweight = 0;
7948  }
7949  }
7950 
7951  return ln_dweight;
7952 }
int weight
Definition: numeric.c:273
static const NumericVar const_zero_point_nine
Definition: numeric.c:410
static const NumericVar const_one
Definition: numeric.c:376
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:7961
int ndigits
Definition: numeric.c:272
#define Abs(x)
Definition: c.h:832
#define NBASE
Definition: numeric.c:94
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6466
static void free_var(NumericVar *var)
Definition: numeric.c:5489
NumericDigit * digits
Definition: numeric.c:277
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6641
#define DEC_DIGITS
Definition: numeric.c:96
static const NumericVar const_one_point_one
Definition: numeric.c:420
#define init_var(v)
Definition: numeric.c:452
int digits
Definition: informix.c:691

◆ exp_var()

static void exp_var ( const NumericVar arg,
NumericVar result,
int  rscale 
)
static

Definition at line 7757 of file numeric.c.

References Abs, add_var(), DEC_DIGITS, div_var_fast(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, Max, mul_var(), NumericVar::ndigits, NUMERIC_MAX_RESULT_SCALE, NUMERIC_MIN_DISPLAY_SCALE, numericvar_to_double_no_overflow(), round_var(), set_var_from_var(), val, and NumericVar::weight.

Referenced by numeric_exp(), and power_var().

7758 {
7759  NumericVar x;
7760  NumericVar elem;
7761  NumericVar ni;
7762  double val;
7763  int dweight;
7764  int ndiv2;
7765  int sig_digits;
7766  int local_rscale;
7767 
7768  init_var(&x);
7769  init_var(&elem);
7770  init_var(&ni);
7771 
7772  set_var_from_var(arg, &x);
7773 
7774  /*
7775  * Estimate the dweight of the result using floating point arithmetic, so
7776  * that we can choose an appropriate local rscale for the calculation.
7777  */
7779 
7780  /* Guard against overflow */
7781  /* If you change this limit, see also power_var()'s limit */
7782  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
7783  ereport(ERROR,
7784  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7785  errmsg("value overflows numeric format")));
7786 
7787  /* decimal weight = log10(e^x) = x * log10(e) */
7788  dweight = (int) (val * 0.434294481903252);
7789 
7790  /*
7791  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
7792  * 2^n, to improve the convergence rate of the Taylor series.
7793  */
7794  if (Abs(val) > 0.01)
7795  {
7796  NumericVar tmp;
7797 
7798  init_var(&tmp);
7799  set_var_from_var(&const_two, &tmp);
7800 
7801  ndiv2 = 1;
7802  val /= 2;
7803 
7804  while (Abs(val) > 0.01)
7805  {
7806  ndiv2++;
7807  val /= 2;
7808  add_var(&tmp, &tmp, &tmp);
7809  }
7810 
7811  local_rscale = x.dscale + ndiv2;
7812  div_var_fast(&x, &tmp, &x, local_rscale, true);
7813 
7814  free_var(&tmp);
7815  }
7816  else
7817  ndiv2 = 0;
7818 
7819  /*
7820  * Set the scale for the Taylor series expansion. The final result has
7821  * (dweight + rscale + 1) significant digits. In addition, we have to
7822  * raise the Taylor series result to the power 2^ndiv2, which introduces
7823  * an error of up to around log10(2^ndiv2) digits, so work with this many
7824  * extra digits of precision (plus a few more for good measure).
7825  */
7826  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
7827  sig_digits = Max(sig_digits, 0) + 8;
7828 
7829  local_rscale = sig_digits - 1;
7830 
7831  /*
7832  * Use the Taylor series
7833  *
7834  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
7835  *
7836  * Given the limited range of x, this should converge reasonably quickly.
7837  * We run the series until the terms fall below the local_rscale limit.
7838  */
7839  add_var(&const_one, &x, result);
7840 
7841  mul_var(&x, &x, &elem, local_rscale);
7842  set_var_from_var(&const_two, &ni);
7843  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7844 
7845  while (elem.ndigits != 0)
7846  {
7847  add_var(result, &elem, result);
7848 
7849  mul_var(&elem, &x, &elem, local_rscale);
7850  add_var(&ni, &const_one, &ni);
7851  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7852  }
7853 
7854  /*
7855  * Compensate for the argument range reduction. Since the weight of the
7856  * result doubles with each multiplication, we can reduce the local rscale
7857  * as we proceed.
7858  */
7859  while (ndiv2-- > 0)
7860  {
7861  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
7862  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7863  mul_var(result, result, result, local_rscale);
7864  }
7865 
7866  /* Round to requested rscale */
7867  round_var(result, rscale);
7868 
7869  free_var(&x);
7870  free_var(&elem);
7871  free_var(&ni);
7872 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8678
int weight
Definition: numeric.c:273
static const NumericVar const_one
Definition: numeric.c:376
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define Abs(x)
Definition: c.h:832
#define ERROR
Definition: elog.h:43
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:6434
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:30
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:32
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7244
#define ereport(elevel, rest)
Definition: elog.h:122
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static const NumericVar const_two
Definition: numeric.c:380
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6762
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6524
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:96
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5739
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3208 of file numeric.c.

References buf, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, isinf(), make_result(), PG_GETARG_FLOAT4, PG_RETURN_NUMERIC, set_var_from_str(), snprintf(), and val.

3209 {
3211  Numeric res;
3212  NumericVar result;
3213  char buf[FLT_DIG + 100];
3214 
3215  if (isnan(val))
3217 
3218  if (isinf(val))
3219  ereport(ERROR,
3220  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3221  errmsg("cannot convert infinity to numeric")));
3222 
3223  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
3224 
3225  init_var(&result);
3226 
3227  /* Assume we need not worry about leading/trailing spaces */
3228  (void) set_var_from_str(buf, buf, &result);
3229 
3230  res = make_result(&result);
3231 
3232  free_var(&result);
3233 
3234  PG_RETURN_NUMERIC(res);
3235 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
int isinf(double x)
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:245
#define ereport(elevel, rest)
Definition: elog.h:122
float float4
Definition: c.h:438
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5529
static const NumericVar const_nan
Definition: numeric.c:423
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6004
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3137 of file numeric.c.

References buf, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, isinf(), make_result(), PG_GETARG_FLOAT8, PG_RETURN_NUMERIC, set_var_from_str(), snprintf(), and val.

3138 {
3140  Numeric res;
3141  NumericVar result;
3142  char buf[DBL_DIG + 100];
3143 
3144  if (isnan(val))
3146 
3147  if (isinf(val))
3148  ereport(ERROR,
3149  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3150  errmsg("cannot convert infinity to numeric")));
3151 
3152  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3153 
3154  init_var(&result);
3155 
3156  /* Assume we need not worry about leading/trailing spaces */
3157  (void) set_var_from_str(buf, buf, &result);
3158 
3159  res = make_result(&result);
3160 
3161  free_var(&result);
3162 
3163  PG_RETURN_NUMERIC(res);
3164 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:246
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:439
int isinf(double x)
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:122
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5529
static const NumericVar const_nan
Definition: numeric.c:423
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6004
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ floor_var()

static void floor_var ( const NumericVar var,
NumericVar result 
)
static

Definition at line 7661 of file numeric.c.

References cmp_var(), free_var(), init_var, NUMERIC_NEG, set_var_from_var(), NumericVar::sign, sub_var(), and trunc_var().

Referenced by compute_bucket(), and numeric_floor().

7662 {
7663  NumericVar tmp;
7664 
7665  init_var(&tmp);
7666  set_var_from_var(var, &tmp);
7667 
7668  trunc_var(&tmp, 0);
7669 
7670  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
7671  sub_var(&tmp, &const_one, &tmp);
7672 
7673  set_var_from_var(&tmp, result);
7674  free_var(&tmp);
7675 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8784
static const NumericVar const_one
Definition: numeric.c:376
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6466
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6641
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5739
#define init_var(v)
Definition: numeric.c:452

◆ free_var()

static void free_var ( NumericVar var)
static

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1368 of file numeric.c.

References generate_series_step_numeric().

1369 {
1370  return generate_series_step_numeric(fcinfo);
1371 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1374

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1374 of file numeric.c.

References add_var(), cmp_var(), const_one, generate_series_numeric_fctx::current, ereport, errcode(), errmsg(), ERROR, init_var, init_var_from_num(), make_result(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, NUMERIC_IS_NAN, NUMERIC_NEG, NUMERIC_POS, NumericGetDatum, palloc(), PG_GETARG_NUMERIC, PG_NARGS, set_var_from_num(), set_var_from_var(), NumericVar::sign, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_series_numeric_fctx::step, generate_series_numeric_fctx::stop, and FuncCallContext::user_fctx.

Referenced by generate_series_numeric().

1375 {
1377  FuncCallContext *funcctx;
1378  MemoryContext oldcontext;
1379 
1380  if (SRF_IS_FIRSTCALL())
1381  {
1382  Numeric start_num = PG_GETARG_NUMERIC(0);
1383  Numeric stop_num = PG_GETARG_NUMERIC(1);
1384  NumericVar steploc = const_one;
1385 
1386  /* handle NaN in start and stop values */
1387  if (NUMERIC_IS_NAN(start_num))
1388  ereport(ERROR,
1389  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1390  errmsg("start value cannot be NaN")));
1391 
1392  if (NUMERIC_IS_NAN(stop_num))
1393  ereport(ERROR,
1394  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1395  errmsg("stop value cannot be NaN")));
1396 
1397  /* see if we were given an explicit step size */
1398  if (PG_NARGS() == 3)
1399  {
1400  Numeric step_num = PG_GETARG_NUMERIC(2);
1401 
1402  if (NUMERIC_IS_NAN(step_num))
1403  ereport(ERROR,
1404  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1405  errmsg("step size cannot be NaN")));
1406 
1407  init_var_from_num(step_num, &steploc);
1408 
1409  if (cmp_var(&steploc, &const_zero) == 0)
1410  ereport(ERROR,
1411  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1412  errmsg("step size cannot equal zero")));
1413  }
1414 
1415  /* create a function context for cross-call persistence */
1416  funcctx = SRF_FIRSTCALL_INIT();
1417 
1418  /*
1419  * Switch to memory context appropriate for multiple function calls.
1420  */
1421  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1422 
1423  /* allocate memory for user context */
1424  fctx = (generate_series_numeric_fctx *)
1426 
1427  /*
1428  * Use fctx to keep state from call to call. Seed current with the
1429  * original start value. We must copy the start_num and stop_num
1430  * values rather than pointing to them, since we may have detoasted
1431  * them in the per-call context.
1432  */
1433  init_var(&fctx->current);
1434  init_var(&fctx->stop);
1435  init_var(&fctx->step);
1436 
1437  set_var_from_num(start_num, &fctx->current);
1438  set_var_from_num(stop_num, &fctx->stop);
1439  set_var_from_var(&steploc, &fctx->step);
1440 
1441  funcctx->user_fctx = fctx;
1442  MemoryContextSwitchTo(oldcontext);
1443  }
1444 
1445  /* stuff done on every call of the function */
1446  funcctx = SRF_PERCALL_SETUP();
1447 
1448  /*
1449  * Get the saved state and use current state as the result of this
1450  * iteration.
1451  */
1452  fctx = funcctx->user_fctx;
1453 
1454  if ((fctx->step.sign == NUMERIC_POS &&
1455  cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1456  (fctx->step.sign == NUMERIC_NEG &&
1457  cmp_var(&fctx->current, &fctx->stop) >= 0))
1458  {
1459  Numeric result = make_result(&fctx->current);
1460 
1461  /* switch to memory context appropriate for iteration calculation */
1462  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1463 
1464  /* increment current in preparation for next iteration */
1465  add_var(&fctx->current, &fctx->step, &fctx->current);
1466  MemoryContextSwitchTo(oldcontext);
1467 
1468  /* do when there is more left to send */
1469  SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1470  }
1471  else
1472  /* do when there is no more left */
1473  SRF_RETURN_DONE(funcctx);
1474 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
static const NumericVar const_one
Definition: numeric.c:376
#define NumericGetDatum(X)
Definition: numeric.h:51
#define NUMERIC_POS
Definition: numeric.c:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5722
#define ereport(elevel, rest)
Definition: elog.h:122
static const NumericVar const_zero
Definition: numeric.c:372
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6466
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void set_var_from_num(Numeric value, NumericVar *dest)
Definition: numeric.c:5691
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6524
#define PG_NARGS()
Definition: fmgr.h:168
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6004
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5739
#define init_var(v)
Definition: numeric.c:452
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 5765 of file numeric.c.

References DEC_DIGITS, NumericVar::digits, NumericVar::dscale, error(), i, NBASE, NumericVar::ndigits, NUMERIC_NEG, palloc(), NumericVar::sign, generate_unaccent_rules::str, and NumericVar::weight.

Referenced by get_str_from_var_sci(), numeric_normalize(), numeric_out(), and numericvar_to_double_no_overflow().

5766 {
5767  int dscale;
5768  char *str;
5769  char *cp;
5770  char *endcp;
5771  int i;
5772  int d;
5773  NumericDigit dig;
5774 
5775 #if DEC_DIGITS > 1
5776  NumericDigit d1;
5777 #endif
5778 
5779  dscale = var->dscale;
5780 
5781  /*
5782  * Allocate space for the result.
5783  *
5784  * i is set to the # of decimal digits before decimal point. dscale is the
5785  * # of decimal digits we will print after decimal point. We may generate
5786  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
5787  * need room for sign, decimal point, null terminator.
5788  */
5789  i = (var->weight + 1) * DEC_DIGITS;
5790  if (i <= 0)
5791  i = 1;
5792 
5793  str = palloc(i + dscale + DEC_DIGITS + 2);
5794  cp = str;
5795 
5796  /*
5797  * Output a dash for negative values
5798  */
5799  if (var->sign == NUMERIC_NEG)
5800  *cp++ = '-';
5801 
5802  /*
5803  * Output all digits before the decimal point
5804  */
5805  if (var->weight < 0)
5806  {
5807  d = var->weight + 1;
5808  *cp++ = '0';
5809  }
5810  else
5811  {
5812  for (d = 0; d <= var->weight; d++)
5813  {
5814  dig = (d < var->ndigits) ? var->digits[d] : 0;
5815  /* In the first digit, suppress extra leading decimal zeroes */
5816 #if DEC_DIGITS == 4
5817  {
5818  bool putit = (d > 0);
5819 
5820  d1 = dig / 1000;
5821  dig -= d1 * 1000;
5822  putit |= (d1 > 0);
5823  if (putit)
5824  *cp++ = d1 + '0';
5825  d1 = dig / 100;
5826  dig -= d1 * 100;
5827  putit |= (d1 > 0);
5828  if (putit)
5829  *cp++ = d1 + '0';
5830  d1 = dig / 10;
5831  dig -= d1 * 10;
5832  putit |= (d1 > 0);
5833  if (putit)
5834  *cp++ = d1 + '0';
5835  *cp++ = dig + '0';
5836  }
5837 #elif DEC_DIGITS == 2
5838  d1 = dig / 10;
5839  dig -= d1 * 10;
5840  if (d1 > 0 || d > 0)
5841  *cp++ = d1 + '0';
5842  *cp++ = dig + '0';
5843 #elif DEC_DIGITS == 1
5844  *cp++ = dig + '0';
5845 #else
5846 #error unsupported NBASE
5847 #endif
5848  }
5849  }
5850 
5851  /*
5852  * If requested, output a decimal point and all the digits that follow it.
5853  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
5854  * needed.
5855  */
5856  if (dscale > 0)
5857  {
5858  *cp++ = '.';
5859  endcp = cp + dscale;
5860  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
5861  {
5862  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
5863 #if DEC_DIGITS == 4
5864  d1 = dig / 1000;
5865  dig -= d1 * 1000;
5866  *cp++ = d1 + '0';
5867  d1 = dig / 100;
5868  dig -= d1 * 100;
5869  *cp++ = d1 + '0';
5870  d1 = dig / 10;
5871  dig -= d1 * 10;
5872  *cp++ = d1 + '0';
5873  *cp++ = dig + '0';
5874 #elif DEC_DIGITS == 2
5875  d1 = dig / 10;
5876  dig -= d1 * 10;
5877  *cp++ = d1 + '0';
5878  *cp++ = dig + '0';
5879 #elif DEC_DIGITS == 1
5880  *cp++ = dig + '0';
5881 #else
5882 #error unsupported NBASE
5883 #endif
5884  }
5885  cp = endcp;
5886  }
5887 
5888  /*
5889  * terminate the string and return it
5890  */
5891  *cp = '\0';
5892  return str;
5893 }
int weight
Definition: numeric.c:273
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
int16 NumericDigit
Definition: numeric.c:100
#define NBASE
Definition: numeric.c:94
NumericDigit * digits
Definition: numeric.c:277
void * palloc(Size size)
Definition: mcxt.c:835
int i
#define DEC_DIGITS
Definition: numeric.c:96

◆ get_str_from_var_sci()

static char * get_str_from_var_sci ( const NumericVar var,
int  rscale 
)
static

Definition at line 5918 of file numeric.c.

References DEC_DIGITS, NumericVar::digits, div_var(), free_var(), get_str_from_var(), init_var, NumericVar::ndigits, palloc(), pfree(), power_var_int(), snprintf(), generate_unaccent_rules::str, and NumericVar::weight.

Referenced by numeric_out_sci().

5919 {
5920  int32 exponent;
5921  NumericVar denominator;
5922  NumericVar significand;
5923  int denom_scale;
5924  size_t len;
5925  char *str;
5926  char *sig_out;
5927 
5928  if (rscale < 0)
5929  rscale = 0;
5930 
5931  /*
5932  * Determine the exponent of this number in normalised form.
5933  *
5934  * This is the exponent required to represent the number with only one
5935  * significant digit before the decimal place.
5936  */
5937  if (var->ndigits > 0)
5938  {
5939  exponent = (var->weight + 1) * DEC_DIGITS;
5940 
5941  /*
5942  * Compensate for leading decimal zeroes in the first numeric digit by
5943  * decrementing the exponent.
5944  */
5945  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
5946  }
5947  else
5948  {
5949  /*
5950  * If var has no digits, then it must be zero.
5951  *
5952  * Zero doesn't technically have a meaningful exponent in normalised
5953  * notation, but we just display the exponent as zero for consistency
5954  * of output.
5955  */
5956  exponent = 0;
5957  }
5958 
5959  /*
5960  * The denominator is set to 10 raised to the power of the exponent.
5961  *
5962  * We then divide var by the denominator to get the significand, rounding
5963  * to rscale decimal digits in the process.
5964  */
5965  if (exponent < 0)
5966  denom_scale = -exponent;
5967  else
5968  denom_scale = 0;
5969 
5970  init_var(&denominator);
5971  init_var(&significand);
5972 
5973  power_var_int(&const_ten, exponent, &denominator, denom_scale);
5974  div_var(var, &denominator, &significand, rscale, true);
5975  sig_out = get_str_from_var(&significand);
5976 
5977  free_var(&denominator);
5978  free_var(&significand);
5979 
5980  /*
5981  * Allocate space for the result.
5982  *
5983  * In addition to the significand, we need room for the exponent
5984  * decoration ("e"), the sign of the exponent, up to 10 digits for the
5985  * exponent itself, and of course the null terminator.
5986  */
5987  len = strlen(sig_out) + 13;
5988  str = palloc(len);
5989  snprintf(str, len, "%se%+03d", sig_out, exponent);
5990 
5991  pfree(sig_out);
5992 
5993  return str;
5994 }
int weight
Definition: numeric.c:273
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int ndigits
Definition: numeric.c:272
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:6959
signed int int32
Definition: c.h:294
void pfree(void *pointer)
Definition: mcxt.c:936
static void power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:8243
static const NumericVar const_ten
Definition: numeric.c:385
static void free_var(NumericVar *var)
Definition: numeric.c:5489
NumericDigit * digits
Definition: numeric.c:277
void * palloc(Size size)
Definition: mcxt.c:835
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:5765
#define DEC_DIGITS
Definition: numeric.c:96
#define init_var(v)
Definition: numeric.c:452

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2169 of file numeric.c.

References Assert, digits, hash_any(), i, NUMERIC_DIGITS, NUMERIC_IS_NAN, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_NUMERIC, PG_RETURN_DATUM, and PG_RETURN_UINT32.

Referenced by JsonbHashScalarValue().

2170 {
2171  Numeric key = PG_GETARG_NUMERIC(0);
2172  Datum digit_hash;
2173  Datum result;
2174  int weight;
2175  int start_offset;
2176  int end_offset;
2177  int i;
2178  int hash_len;
2180 
2181  /* If it's NaN, don't try to hash the rest of the fields */
2182  if (NUMERIC_IS_NAN(key))
2183  PG_RETURN_UINT32(0);
2184 
2185  weight = NUMERIC_WEIGHT(key);
2186  start_offset = 0;
2187  end_offset = 0;
2188 
2189  /*
2190  * Omit any leading or trailing zeros from the input to the hash. The
2191  * numeric implementation *should* guarantee that leading and trailing
2192  * zeros are suppressed, but we're paranoid. Note that we measure the
2193  * starting and ending offsets in units of NumericDigits, not bytes.
2194  */
2195  digits = NUMERIC_DIGITS(key);
2196  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2197  {
2198  if (digits[i] != (NumericDigit) 0)
2199  break;
2200 
2201  start_offset++;
2202 
2203  /*
2204  * The weight is effectively the # of digits before the decimal point,
2205  * so decrement it for each leading zero we skip.
2206  */
2207  weight--;
2208  }
2209 
2210  /*
2211  * If there are no non-zero digits, then the value of the number is zero,
2212  * regardless of any other fields.
2213  */
2214  if (NUMERIC_NDIGITS(key) == start_offset)
2215  PG_RETURN_UINT32(-1);
2216 
2217  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2218  {
2219  if (digits[i] != (NumericDigit) 0)
2220  break;
2221 
2222  end_offset++;
2223  }
2224 
2225  /* If we get here, there should be at least one non-zero digit */
2226  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2227 
2228  /*
2229  * Note that we don't hash on the Numeric's scale, since two numerics can
2230  * compare equal but have different scales. We also don't hash on the
2231  * sign, although we could: since a sign difference implies inequality,
2232  * this shouldn't affect correctness.
2233  */
2234  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2235  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2236  hash_len * sizeof(NumericDigit));
2237 
2238  /* Mix in the weight, via XOR */
2239  result = digit_hash ^ weight;
2240 
2241  PG_RETURN_DATUM(result);
2242 }
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:315
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
int16 NumericDigit
Definition: numeric.c:100
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:680
Datum hash_any(register const unsigned char *k, register int keylen)
Definition: hashfunc.c:428
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
int digits
Definition: informix.c:691

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2249 of file numeric.c.

References Assert, DatumGetUInt64, digits, hash_any_extended(), i, NUMERIC_DIGITS, NUMERIC_IS_NAN, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_INT64, PG_GETARG_NUMERIC, PG_RETURN_DATUM, PG_RETURN_UINT64, and UInt64GetDatum.

Referenced by JsonbHashScalarValueExtended().

2250 {
2251  Numeric key = PG_GETARG_NUMERIC(0);
2252  uint64 seed = PG_GETARG_INT64(1);
2253  Datum digit_hash;
2254  Datum result;
2255  int weight;
2256  int start_offset;
2257  int end_offset;
2258  int i;
2259  int hash_len;
2261 
2262  if (NUMERIC_IS_NAN(key))
2263  PG_RETURN_UINT64(seed);
2264 
2265  weight = NUMERIC_WEIGHT(key);
2266  start_offset = 0;
2267  end_offset = 0;
2268 
2269  digits = NUMERIC_DIGITS(key);
2270  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2271  {
2272  if (digits[i] != (NumericDigit) 0)
2273  break;
2274 
2275  start_offset++;
2276 
2277  weight--;
2278  }
2279 
2280  if (NUMERIC_NDIGITS(key) == start_offset)
2281  PG_RETURN_UINT64(seed - 1);
2282 
2283  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2284  {
2285  if (digits[i] != (NumericDigit) 0)
2286  break;
2287 
2288  end_offset++;
2289  }
2290 
2291  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2292 
2293  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2294  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2295  + start_offset),
2296  hash_len * sizeof(NumericDigit),
2297  seed);
2298 
2299  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2300 
2301  PG_RETURN_DATUM(result);
2302 }
#define UInt64GetDatum(X)
Definition: postgres.h:654
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:328
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
int16 NumericDigit
Definition: numeric.c:100
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define DatumGetUInt64(X)
Definition: postgres.h:640
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:680
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
Datum hash_any_extended(register const unsigned char *k, register int keylen, uint64 seed)
Definition: hashfunc.c:634
int digits
Definition: informix.c:691

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 5722 of file numeric.c.

References NumericVar::buf, NumericVar::digits, NumericVar::dscale, NumericVar::ndigits, NUMERIC_DIGITS, NUMERIC_DSCALE, NUMERIC_NDIGITS, NUMERIC_SIGN, NUMERIC_WEIGHT, NumericVar::sign, and NumericVar::weight.

Referenced by compute_bucket(), do_numeric_accum(), do_numeric_discard(), generate_series_step_numeric(), int8_avg_deserialize(), numeric_abbrev_convert(), numeric_add(), numeric_avg_deserialize(), numeric_ceil(), numeric_deserialize(), numeric_div(), numeric_div_trunc(), numeric_exp(), numeric_floor(), numeric_inc(), numeric_int2(), numeric_int4(), numeric_int8(), numeric_ln(), numeric_log(), numeric_mod(), numeric_mul(), numeric_normalize(), numeric_out(), numeric_out_sci(), numeric_poly_deserialize(), numeric_power(), numeric_send(), numeric_sqrt(), and numeric_sub().

5723 {
5724  dest->ndigits = NUMERIC_NDIGITS(num);
5725  dest->weight = NUMERIC_WEIGHT(num);
5726  dest->sign = NUMERIC_SIGN(num);
5727  dest->dscale = NUMERIC_DSCALE(num);
5728  dest->digits = NUMERIC_DIGITS(num);
5729  dest->buf = NULL; /* digits array is not palloc'd */
5730 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:211
int weight
Definition: numeric.c:273
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
int sign
Definition: numeric.c:274
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
#define NUMERIC_SIGN(n)
Definition: numeric.c:207
NumericDigit * buf
Definition: numeric.c:276
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
NumericDigit * digits
Definition: numeric.c:277

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 4020 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int2_numeric(), makePolyNumAggState, newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4021 {
4023 
4024  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4025 
4026  /* Create the state data on the first call */
4027  if (state == NULL)
4028  state = makePolyNumAggState(fcinfo, true);
4029 
4030  if (!PG_ARGISNULL(1))
4031  {
4032 #ifdef HAVE_INT128
4033  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
4034 #else
4035  Numeric newval;
4036 
4038  PG_GETARG_DATUM(1)));
4039  do_numeric_accum(state, newval);
4040 #endif
4041  }
4042 
4043  PG_RETURN_POINTER(state);
4044 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3083
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3330
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4015

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4497 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int2_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4498 {
4500 
4501  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4502 
4503  /* Should not get here with no state */
4504  if (state == NULL)
4505  elog(ERROR, "int2_accum_inv called with NULL state");
4506 
4507  if (!PG_ARGISNULL(1))
4508  {
4509 #ifdef HAVE_INT128
4510  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4511 #else
4512  Numeric newval;
4513 
4515  PG_GETARG_DATUM(1)));
4516 
4517  /* Should never fail, all inputs have dscale 0 */
4518  if (!do_numeric_discard(state, newval))
4519  elog(ERROR, "do_numeric_discard failed unexpectedly");
4520 #endif
4521  }
4522 
4523  PG_RETURN_POINTER(state);
4524 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3083
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3395
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5188 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT16, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5189 {
5190  ArrayType *transarray;
5192  Int8TransTypeData *transdata;
5193 
5194  /*
5195  * If we're invoked as an aggregate, we can cheat and modify our first
5196  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5197  * a copy of it before scribbling on it.
5198  */
5199  if (AggCheckCallContext(fcinfo, NULL))
5200  transarray = PG_GETARG_ARRAYTYPE_P(0);
5201  else
5202  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5203 
5204  if (ARR_HASNULL(transarray) ||
5205  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5206  elog(ERROR, "expected 2-element int8 array");
5207 
5208  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5209  transdata->count++;
5210  transdata->sum += newval;
5211 
5212  PG_RETURN_ARRAYTYPE_P(transarray);
5213 }
signed short int16
Definition: c.h:293
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define elog
Definition: elog.h:219

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5275 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT16, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5276 {
5277  ArrayType *transarray;
5279  Int8TransTypeData *transdata;
5280 
5281  /*
5282  * If we're invoked as an aggregate, we can cheat and modify our first
5283  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5284  * a copy of it before scribbling on it.
5285  */
5286  if (AggCheckCallContext(fcinfo, NULL))
5287  transarray = PG_GETARG_ARRAYTYPE_P(0);
5288  else
5289  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5290 
5291  if (ARR_HASNULL(transarray) ||
5292  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5293  elog(ERROR, "expected 2-element int8 array");
5294 
5295  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5296  transdata->count--;
5297  transdata->sum -= newval;
5298 
5299  PG_RETURN_ARRAYTYPE_P(transarray);
5300 }
signed short int16
Definition: c.h:293
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define elog
Definition: elog.h:219

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3083 of file numeric.c.

References free_var(), init_var, int64_to_numericvar(), make_result(), PG_GETARG_INT16, PG_RETURN_NUMERIC, and val.

Referenced by int2_accum(), and int2_accum_inv().

3084 {
3085  int16 val = PG_GETARG_INT16(0);
3086  Numeric res;
3087  NumericVar result;
3088 
3089  init_var(&result);
3090 
3091  int64_to_numericvar((int64) val, &result);
3092 
3093  res = make_result(&result);
3094 
3095  free_var(&result);
3096 
3097  PG_RETURN_NUMERIC(res);
3098 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:293
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6004
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6242
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 5036 of file numeric.c.

References AggCheckCallContext(), newval, PG_ARGISNULL, PG_GETARG_INT16, PG_GETARG_INT64, PG_GETARG_POINTER, PG_RETURN_INT64, PG_RETURN_NULL, and PG_RETURN_POINTER.

5037 {
5038  int64 newval;
5039 
5040  if (PG_ARGISNULL(0))
5041  {
5042  /* No non-null input seen so far... */
5043  if (PG_ARGISNULL(1))
5044  PG_RETURN_NULL(); /* still no non-null */
5045  /* This is the first non-null input. */
5046  newval = (int64) PG_GETARG_INT16(1);
5047  PG_RETURN_INT64(newval);
5048  }
5049 
5050  /*
5051  * If we're invoked as an aggregate, we can cheat and modify our first
5052  * parameter in-place to avoid palloc overhead. If not, we need to return
5053  * the new value of the transition variable. (If int8 is pass-by-value,
5054  * then of course this is useless as well as incorrect, so just ifdef it
5055  * out.)
5056  */
5057 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5058  if (AggCheckCallContext(fcinfo, NULL))
5059  {
5060  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5061 
5062  /* Leave the running sum unchanged in the new input is null */
5063  if (!PG_ARGISNULL(1))
5064  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
5065 
5066  PG_RETURN_POINTER(oldsum);
5067  }
5068  else
5069 #endif
5070  {
5071  int64 oldsum = PG_GETARG_INT64(0);
5072 
5073  /* Leave sum unchanged if new input is null. */
5074  if (PG_ARGISNULL(1))
5075  PG_RETURN_INT64(oldsum);
5076 
5077  /* OK to do the addition. */
5078  newval = oldsum + (int64) PG_GETARG_INT16(1);
5079 
5080  PG_RETURN_INT64(newval);
5081  }
5082 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5360 of file numeric.c.

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, dump_numeric, dump_var, elog, ERROR, i, Int64GetDatumFast, NumericVar::ndigits, NUMERIC_DIGITS, NUMERIC_DSCALE, NUMERIC_NAN, NUMERIC_NDIGITS, NUMERIC_NEG, NUMERIC_POS, NUMERIC_SIGN, NUMERIC_WEIGHT, PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, NumericVar::sign, generate_unaccent_rules::str, Int8TransTypeData::sum, and NumericVar::weight.

5361 {
5362  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5363  Int8TransTypeData *transdata;
5364 
5365  if (ARR_HASNULL(transarray) ||
5366  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5367  elog(ERROR, "expected 2-element int8 array");
5368  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5369 
5370  /* SQL defines SUM of no values to be NULL */
5371  if (transdata->count == 0)
5372  PG_RETURN_NULL();
5373 
5374  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5375 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define Int64GetDatumFast(X)
Definition: postgres.h:781
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 4047 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int4_numeric(), makePolyNumAggState, newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT32, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4048 {
4050 
4051  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4052 
4053  /* Create the state data on the first call */
4054  if (state == NULL)
4055  state = makePolyNumAggState(fcinfo, true);
4056 
4057  if (!PG_ARGISNULL(1))
4058  {
4059 #ifdef HAVE_INT128
4060  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
4061 #else
4062  Numeric newval;
4063 
4065  PG_GETARG_DATUM(1)));
4066  do_numeric_accum(state, newval);
4067 #endif
4068  }
4069 
4070  PG_RETURN_POINTER(state);
4071 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3330
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2973
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4015

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4527 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int4_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT32, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4528 {
4530 
4531  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4532 
4533  /* Should not get here with no state */
4534  if (state == NULL)
4535  elog(ERROR, "int4_accum_inv called with NULL state");
4536 
4537  if (!PG_ARGISNULL(1))
4538  {
4539 #ifdef HAVE_INT128
4540  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
4541 #else
4542  Numeric newval;
4543 
4545  PG_GETARG_DATUM(1)));
4546 
4547  /* Should never fail, all inputs have dscale 0 */
4548  if (!do_numeric_discard(state, newval))
4549  elog(ERROR, "do_numeric_discard failed unexpectedly");
4550 #endif
4551  }
4552 
4553  PG_RETURN_POINTER(state);
4554 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3395
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2973
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5216 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT32, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5217 {
5218  ArrayType *transarray;
5220  Int8TransTypeData *transdata;
5221 
5222  /*
5223  * If we're invoked as an aggregate, we can cheat and modify our first
5224  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5225  * a copy of it before scribbling on it.
5226  */
5227  if (AggCheckCallContext(fcinfo, NULL))
5228  transarray = PG_GETARG_ARRAYTYPE_P(0);
5229  else
5230  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5231 
5232  if (ARR_HASNULL(transarray) ||
5233  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5234  elog(ERROR, "expected 2-element int8 array");
5235 
5236  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5237  transdata->count++;
5238  transdata->sum += newval;
5239 
5240  PG_RETURN_ARRAYTYPE_P(transarray);
5241 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
signed int int32
Definition: c.h:294
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define elog
Definition: elog.h:219

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5303 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT32, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5304 {
5305  ArrayType *transarray;
5307  Int8TransTypeData *transdata;
5308 
5309  /*
5310  * If we're invoked as an aggregate, we can cheat and modify our first
5311  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5312  * a copy of it before scribbling on it.
5313  */
5314  if (AggCheckCallContext(fcinfo, NULL))
5315  transarray = PG_GETARG_ARRAYTYPE_P(0);
5316  else
5317  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5318 
5319  if (ARR_HASNULL(transarray) ||
5320  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5321  elog(ERROR, "expected 2-element int8 array");
5322 
5323  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5324  transdata->count--;
5325  transdata->sum -= newval;
5326 
5327  PG_RETURN_ARRAYTYPE_P(transarray);
5328 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
signed int int32
Definition: c.h:294
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define elog
Definition: elog.h:219

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5244 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, PG_GETARG_ARRAYTYPE_P, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5245 {
5246  ArrayType *transarray1;
5247  ArrayType *transarray2;
5248  Int8TransTypeData *state1;
5249  Int8TransTypeData *state2;
5250 
5251  if (!AggCheckCallContext(fcinfo, NULL))
5252  elog(ERROR, "aggregate function called in non-aggregate context");
5253 
5254  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5255  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5256 
5257  if (ARR_HASNULL(transarray1) ||
5258  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5259  elog(ERROR, "expected 2-element int8 array");
5260 
5261  if (ARR_HASNULL(transarray2) ||
5262  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5263  elog(ERROR, "expected 2-element int8 array");
5264 
5265  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5266  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5267 
5268  state1->count += state2->count;
5269  state1->sum += state2->sum;
5270 
5271  PG_RETURN_ARRAYTYPE_P(transarray1);
5272 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define elog
Definition: elog.h:219

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2973 of file numeric.c.

References free_var(), init_var, int64_to_numericvar(), make_result(), PG_GETARG_INT32, PG_RETURN_NUMERIC, and val.

Referenced by gbt_numeric_penalty(), int4_accum(), int4_accum_inv(), numeric_to_char(), and numeric_to_number().

2974 {
2975  int32 val = PG_GETARG_INT32(0);
2976  Numeric res;
2977  NumericVar result;
2978 
2979  init_var(&result);
2980 
2981  int64_to_numericvar((int64) val, &result);
2982 
2983  res = make_result(&result);
2984 
2985  free_var(&result);
2986 
2987  PG_RETURN_NUMERIC(res);
2988 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
signed int int32
Definition: c.h:294
static void free_var(NumericVar *var)
Definition: numeric.c:5489
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6004
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6242
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5085 of file numeric.c.

References AggCheckCallContext(), newval, PG_ARGISNULL, PG_GETARG_INT32, PG_GETARG_INT64, PG_GETARG_POINTER, PG_RETURN_INT64, PG_RETURN_NULL, and PG_RETURN_POINTER.

5086 {
5087  int64 newval;
5088 
5089  if (PG_ARGISNULL(0))
5090  {
5091  /* No non-null input seen so far... */
5092  if (PG_ARGISNULL(1))
5093  PG_RETURN_NULL(); /* still no non-null */
5094  /* This is the first non-null input. */
5095  newval = (int64) PG_GETARG_INT32(1);
5096  PG_RETURN_INT64(newval);
5097  }
5098 
5099  /*
5100  * If we're invoked as an aggregate, we can cheat and modify our first
5101  * parameter in-place to avoid palloc overhead. If not, we need to return
5102  * the new value of the transition variable. (If int8 is pass-by-value,
5103  * then of course this is useless as well as incorrect, so just ifdef it
5104  * out.)
5105  */
5106 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5107  if (AggCheckCallContext(fcinfo, NULL))
5108  {
5109  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5110 
5111  /* Leave the running sum unchanged in the new input is null */
5112  if (!PG_ARGISNULL(1))
5113  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
5114 
5115  PG_RETURN_POINTER(oldsum);
5116  }
5117  else
5118 #endif
5119  {
5120  int64 oldsum = PG_GETARG_INT64(0);
5121 
5122  /* Leave sum unchanged if new input is null. */
5123  if (PG_ARGISNULL(1))
5124  PG_RETURN_INT64(oldsum);
5125 
5126  /* OK to do the addition. */
5127  newval = oldsum + (int64) PG_GETARG_INT32(1);
5128 
5129  PG_RETURN_INT64(newval);
5130  }
5131 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3471
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 6242 of file numeric.c.

References alloc_var(), Assert, DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, free_var(), i, init_var, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, round_var(), set_var_from_var(), NumericVar::sign, strip_var(), val, and NumericVar::weight.

Referenced by int2_numeric(), int4_numeric(), int8_numeric(), numeric_fac(), numeric_stddev_internal(), and width_bucket_numeric().

6243 {
6244  uint64 uval,
6245  newuval;
6246  NumericDigit *ptr;
6247  int ndigits;
6248 
6249  /* int64 can require at most 19 decimal digits; add one for safety */
6250  alloc_var(var, 20 / DEC_DIGITS);
6251  if (val < 0)
6252  {
6253  var->sign = NUMERIC_NEG;
6254  uval = -val;
6255  }
6256  else
6257  {
6258  var->sign = NUMERIC_POS;
6259  uval = val;
6260  }
6261  var->dscale = 0;
6262  if (val == 0)
6263  {
6264  var->ndigits = 0;
6265  var->weight = 0;
6266  return;
6267  }
6268  ptr = var->digits + var->ndigits;
6269  ndigits = 0;
6270  do
6271  {
6272  ptr--;
6273  ndigits++;
6274  newuval = uval / NBASE;
6275  *ptr = uval - newuval * NBASE;
6276  uval = newuval;
6277  } while (uval);
6278  var->digits = ptr;
6279  var->ndigits = ndigits;
6280  var->weight = ndigits - 1;
6281 }
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
int16 NumericDigit
Definition: numeric.c:100
#define NBASE
Definition: numeric.c:94
NumericDigit * digits
Definition: numeric.c:277
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5473
#define DEC_DIGITS
Definition: numeric.c:96
long val
Definition: informix.c:689

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 4074 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int8_numeric(), makeNumericAggState(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4075 {
4077 
4078  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4079 
4080  /* Create the state data on the first call */
4081  if (state == NULL)
4082  state = makeNumericAggState(fcinfo, true);
4083 
4084  if (!PG_ARGISNULL(1))
4085  {
4086  Numeric newval;
4087 
4089  PG_GETARG_DATUM(1)));
4090  do_numeric_accum(state, newval);
4091  }
4092 
4093  PG_RETURN_POINTER(state);
4094 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3039
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:3290
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3330
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval

◆ int8_accum_inv()

Datum int8_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4557 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int8_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4558 {
4560 
4561  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4562 
4563  /* Should not get here with no state */
4564  if (state == NULL)
4565  elog(ERROR, "int8_accum_inv called with NULL state");
4566 
4567  if (!PG_ARGISNULL(1))
4568  {
4569  Numeric newval;
4570 
4572  PG_GETARG_DATUM(1)));
4573 
4574  /* Should never fail, all inputs have dscale 0 */
4575  if (!do_numeric_discard(state, newval))
4576  elog(ERROR, "do_numeric_discard failed unexpectedly");
4577  }
4578 
4579  PG_RETURN_POINTER(state);
4580 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3395
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3039
#define ERROR
Definition: elog.h:43
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219

◆ int8_avg()

Datum int8_avg ( PG_FUNCTION_ARGS  )

Definition at line 5331 of file numeric.c.

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, DirectFunctionCall1, DirectFunctionCall2, elog, ERROR, Int64GetDatumFast, int8_numeric(), numeric_div(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, and Int8TransTypeData::sum.

5332 {
5333  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5334  Int8TransTypeData *transdata;
5335  Datum countd,
5336  sumd;
5337 
5338  if (ARR_HASNULL(transarray) ||
5339  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5340  elog(ERROR, "expected 2-element int8 array");
5341  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5342 
5343  /* SQL defines AVG of no values to be NULL */
5344  if (transdata->count == 0)
5345  PG_RETURN_NULL();
5346 
5348  Int64GetDatumFast(transdata->count));
5350  Int64GetDatumFast(transdata->sum));
5351 
5353 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3039
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:2437
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define Int64GetDatumFast(X)
Definition: postgres.h:781
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 4300 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int8_numeric(), makePolyNumAggState, newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4301 {
4303 
4304  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4305 
4306  /* Create the state data on the first call */
4307  if (state == NULL)
4308  state = makePolyNumAggState(fcinfo, false);
4309 
4310  if (!PG_ARGISNULL(1))
4311  {
4312 #ifdef HAVE_INT128
4313  do_int128_accum(state, (int128) PG_GETARG_INT64(1));
4314 #else
4315  Numeric newval;
4316 
4318  PG_GETARG_DATUM(1)));
4319  do_numeric_accum(state, newval);
4320 #endif
4321  }
4322 
4323  PG_RETURN_POINTER(state);
4324 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3039
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3330
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define makePolyNumAggState
Definition: numeric.c:4015

◆ int8_avg_accum_inv()

Datum int8_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4583 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int8_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4584 {
4586 
4587  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4588 
4589  /* Should not get here with no state */
4590  if (state == NULL)
4591  elog(ERROR, "int8_avg_accum_inv called with NULL state");
4592 
4593  if (!PG_ARGISNULL(1))
4594  {
4595 #ifdef HAVE_INT128
4596  do_int128_discard(state, (int128) PG_GETARG_INT64(1));
4597 #else
4598  Numeric newval;
4599 
4601  PG_GETARG_DATUM(1)));
4602 
4603  /* Should never fail, all inputs have dscale 0 */
4604  if (!do_numeric_discard(state, newval))
4605  elog(ERROR, "do_numeric_discard failed unexpectedly");
4606 #endif
4607  }
4608 
4609  PG_RETURN_POINTER(state);
4610 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3395